在C/C++中,有一個經常使用的宏:NULL。在C語言中,通常定義爲((void*)0),也容許定義成0,在C++中,NULL必須是0。函數
即:指針
#ifndef NULL #ifdef __cplusplus #define NULL 0 // C++ #else #define NULL ((void *)0) // C語言的一般定義 如今的C語言(C99)如今已經支持用「//」註釋 #endif #endif
這樣的定義,一不留神就會引發誤解:code
void Func(char*) { std::cout << "Func(char*)" << std::endl; } void Func(int) { std::cout << "Func(int)" << std::endl; } int main() { Func(NULL); // Func(int) return 0; }
因爲咱們常常用NULL表示空指針,因此上面的代碼容易被誤認爲是調用第一個Func,但實際上,因爲NULL在C++中是0,因此調用了第二個。編譯器
在頭腦清醒的時候,這不是什麼問題,但隨着代碼量的增長,咱們很難把注意力集中到這個細節上,就算注意到了這個問題,它也會成爲沒必要要的心智負擔。編譯
nullptr應運而生。class
nullptr是std::nullptr_t類型的(constexpr)變量。std::nullptr_t能夠顯式或隱式地轉換爲任何指針(包括類的成員函數指針),但不能顯式或隱式地轉換爲任何其餘類型。變量
使用nullptr能夠消除這個誤會,例如,上面的代碼,調用Func(nullptr)必定輸出Func(char*)。註釋
其實,C++11將NULL從新定義效果會更好一些,但多是考慮到已經有太多的代碼用了NULL,爲了使得之前的代碼仍任可用,因此才新增的nullptr吧。語言
最後,補充一些細節:di
1)std::nullptr_t不能用於算術表達式,即,不能+、-、*等;
2)std::nullptr_t能夠用於關係表達式,兩個std::nullptr_t類型的變量,進行==、<=、>=運算都會返回true,其餘的關係運算返回false;
3)nullptr不能進行&(取地址)運算。
若是你的編譯器不支持C++11,能夠用C++98/C++03模擬一個nullptr:
// 不支持C++11的編譯器 class nullptr_tt { public: template<class _Tx> operator _Tx*() const { return 0; } template<class _Tx, class _Ty> operator _Ty _Tx::*() const{ return 0; } private: void operator& () const; // 不容許取地址 }; const nullptr_tt nullptr;