在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;