摘要:和宋體標準不僅定義了指針空值常量,也定義了其指針空值類型,也就表示了指針空值類型并非僅有一個實例。標準嚴格規定了數據間的關系。
在C++程序開發中,為了提高代碼的健壯性,一般會在定義指針的同時會完成初始化操作(避免出現野指針),在指針指向尚未明確的情況下,都會給指針初始化為空指針。在C++98/03標準中,將一個指針初始化為空指針的方式有兩種:
char *my_ptr = 0;char *my_ptr = NULL;
在底層源碼中 NULL 這個宏是這樣定義的:
#ifndef NULL#ifdef __cplusplus#define NULL 0#else#define NULL ((void *)0)#endif#endif
可以看出,NULL可能被定義為字面常量0,或者是定義為無類型指針(void*)0
。
原因: 由于 C++ 中, void *
類型無法隱式轉換為其他類型的指針,此時使用 0 代替 ((void *)0)
,用于解決空指針的問題。這個 0(0x0000 0000)表示的就是虛擬地址空間中的 0 地址,這塊地址是只讀的。但是無論采用什么樣的定義方式,我們在使用空值的指針時,都不可避免地會遇到一些麻煩;
如下代碼:
#include using namespace std;void fun(char *c){ cout << "void func(char *c)" << endl;}void fun(int i){ cout << "void func(int i)" << endl;}int main(){ // 想要調用重載函數 void func(char *p) func(NULL); //注:如果使用gcc編譯,NULL轉化為內部標識 __null,該語句會編譯失敗 // 想要調用重載函數 void func(int i) func(0); func((char*)0); return 0;}
輸出:
void func(int i)void func(int i)void func(char *c)
雖然調用func(NULL)
; 最終鏈接到的還是void func(int p)
和預期是不一樣的;
原因: C++ 中將NULL
定義為字面常量 0,并不能保證在所有場景下都能很好的工作,比如,函數重載時,NULL
和 0 無法區分;
在C++11新標準中,出于兼容性的考慮,字面常量0的二義性并沒有被消除;但是新標準為二義性給出了新的答案,就是使用 nullptr
;在C++11 新標準中, nullptr
是一個所謂“指針空值類型”的常量;指針空值類型被命名為 nullptr_t
。
可以在支持 nullptr
的頭文件(csddef)中找到如下定義:
typedef decltype(nullptr) nullptr_t;
使用 nullptr_t
的時候必須#include(#include有些頭文件也會間接#include,比如),而 nullptr
則不用。
大概就是由于 nullptr
是關鍵字,而 nullptr_t
是通過 decltype
推導而來的緣故。
對上述程序進行修改:
#include using namespace std;void fun(char *c){ cout << "void func(char *c)" << endl;}void fun(int i){ cout << "void func(int i)" << endl;}int main(){ //調用重載函數 void func(char *p) func(nullptr); //調用重載函數 void func(int i) func(0); return 0;}
結果:
void func(char *c)void func(int i)
可以看出,nullptr
無法隱式轉換為整形,但是可以隱式匹配指針類型。在 C++11 標準下,相比NULL
和 0,使用 nullptr
初始化空指針可以令我們編寫的程序更加健壯。
C++11標準不僅定義了指針空值常量nullptr
,也定義了其指針空值類型nullptr_t
,也就表示了指針空值類型并非僅有nullptr
一個實例。通常情況下,也可以通過nullptr_t
來聲明一個指針空值類型的變量(即使看起來用途不大)。
除去nullptr
及nullptr_t
以外,C++中還存在各種內置類型。C++11標準嚴格規定了數據間的關系。常見的規則簡單地列在了下面:
①、所有定義為
nullptr_t
類型的數據都是等價的,行為也是完全一致。②、
nullptr_t
類型數據可以隱式轉換成任意一個指針類型。③、
nullptr_t
類型數據不能轉換為非指針類型,即使使用reinterpret_cast()的方式也是不可以的。 ④、
nullptr_t
類型數據不適用于算術運算表達式。⑤、
nullptr_t
類型數據可以用于關系運算表達式,但僅能與nullptr_t類型數據或者指針類型數據進行比較,當且僅當關系運算符為==、<=、>=等時返回true。
①、在C++11標準中,nullptr
類型數據所占用的內存空間大小跟void*
相同的,即:
sizeof(nullptr_t) == sizeof(void*)
注:nullptr
是否是(void *)0
的一個別名?
不是,盡管兩者看起來很相似,都可以被轉換為任何類型的指針,但兩者在語法層面有著不同的內涵。nullptr
是一個編譯時期的常量,它的名字是一個編譯時期的關鍵字,能夠為編譯器所識別。而(void*)0
只是一個強制轉換表達式,其返回的也是一個 void *
指針類型。最為重要的是,在C++語言中,nullptr
到任何指針的轉換是隱式的,而 (void*)0
則必須經過類型轉換后才能使用。
可以關注公眾號:Kevin的嵌入式學習站,創作不易,但您的點贊、關注、收藏就是對我最大的鼓勵!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/123502.html
文章目錄 前言extern C引用1.概念2.語法3.引用特性4.常量引用5.引用做函數返回值6.引用注意點7.傳值、傳引用效率比較 內聯函數1.概念2.特性 auto關鍵字1.概念2.auto的使用細則3.auto不能推導的場景 基于范圍的for循環(C++11)使用條件 指針空值nullptr 前言 承接上文入門篇1,博主這次將會繼續更新以下內容:extern ,引用 ,內聯, a...
摘要:在大型的工程中,自己定義的變量函數,類名與其他人定義的相沖突等問題。使用標準輸出控制臺和標準輸入鍵盤時,必須包含頭文件以及標準命名空間。缺省參數概念缺省參數是聲明或定義函數時為函數的參數指定一個默認值。 目錄 前言 1.命名空間 1.1命名空間定義 1.2 命名空間使用 2. C++的輸入和...
摘要:第一步打開項目下的文件,在文件中輸入我們的函數的原型聲明代碼。這行代碼注冊一個原型為的函數,當這個函數被執行的時候,我們的函數將被運行時調用。原文地址開發擴展之原生函數定義 在上一篇中我們在hellozapi擴展中我們定義了幾個常量,但是一個有用的擴展,必須得有函數,沒有函數的擴展啥用沒有,如果您覺得定義函數很難的話,您又錯了,zendAPI就是為了讓您生活變得美好而生的,而不會讓事情...
閱讀 1614·2021-11-16 11:45
閱讀 2543·2021-09-29 09:48
閱讀 3269·2021-09-07 10:26
閱讀 1840·2021-08-16 10:50
閱讀 1866·2019-08-30 15:44
閱讀 2697·2019-08-28 18:03
閱讀 1897·2019-08-27 10:54
閱讀 1821·2019-08-26 14:01