熟悉C++的童鞋都知道,為了避免“野指針”(即指針在首次使用之前沒有進行初始化)的出現(xiàn),我們聲明一個指針后最好馬上對其進行初始化操作。如果暫時不明確該指針指向哪個變量,則需要賦予NULL值。除了NULL之外,C++11新標準中又引入了nullptr來聲明一個“空指針”,這樣,我們就有下面三種方法來獲取一個“空指針”,如下:
int?*p1?=?NULL;? int?*p2?=?0; int?*p3?=?nullptr;
新標準中建議使用nullptr代替NULL來聲明空指針。到這里,大家心里有沒有疑問:為什么C++11要引入nullptr?它與NULL相比又有什么不同呢?這就是我們今天要解決的問題。
C/C++中的NULL到底是什么
我們查看一下C和C++的源碼,不難發(fā)現(xiàn):
1.NULL在C++中的定義,NULL在C++中被明確定義為整數(shù)0:
/*?Define?NULL?pointer?value?*/ #ifndef?NULL ????#ifdef?__cplusplus ????????#define?NULL????0 ????#else??/*?__cplusplus?*/ ????????#define?NULL????((void?*)0) ????#endif??/*?__cplusplus?*/ #endif??/*?NULL?*/
2.NULL在C中的定義,在C中,NULL通常被定義為如下:
#define?NULL????((void?*)0)
也就是說NULL實質(zhì)上是一個void *指針。
那么問題又來了,我們從一開始學(xué)習(xí)C++的時候就被告誡C++是兼容C的,為什么對于NULL,C++卻不完全兼容C呢?通過查找維基百科,才發(fā)現(xiàn)這其中的原因。
簡單地說,C++之所以做出這樣的選擇,根本原因和C++的函數(shù)重載機制有關(guān)。考慮下面這段代碼:
void?Func(char?*); void?Func(int); int?main() { ????Func(NULL); }
如果C++讓NULL也支持void *的隱式類型轉(zhuǎn)換,這樣編譯器就不知道應(yīng)該調(diào)用哪一個函數(shù)。
為什么要引入nullptr
C++把NULL定義為0,解決了函數(shù)重載后的函數(shù)匹配問題,但是又引入了另一個“問題”,同樣是上面這段代碼:
void?Func(char?*); void?Func(int); int?main() { ????Func(NULL);??//?調(diào)用Func(int) }
由于我們經(jīng)常使用NULL表示空指針,所以從程序員的角度來看,F(xiàn)unc(NULL)應(yīng)該調(diào)用的是Func(char *)但實際上NULL的值是0,所以調(diào)用了Func(int)。nullptr關(guān)鍵字真是為了解決這個問題而引入的。
另外我們還有注意到NULL只是一個宏定義,而nullptr是一個C++關(guān)鍵字。
nullptr如何使用
nullptr關(guān)鍵字用于標識空指針,是std::nullptr_t類型的(constexpr)變量。它可以轉(zhuǎn)換成任何指針類型和bool布爾類型(主要是為了兼容普通指針可以作為條件判斷語句的寫法),但是不能被轉(zhuǎn)換為整數(shù)。
char?*p1?=?nullptr;?????//?正確 int??*p2?=?nullptr;?????//?正確 bool?b?=?nullptr;???????//?正確.?if(b)判斷為false int?a?=?nullptr;????????//?error