2019独角兽企业重金招聘Python工程师标准>>>
在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
这样的定义,一不留神就会引起误解:
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应运而生。
nullptr是std::nullptr_t类型的(constexpr)变量。std::nullptr_t可以显式或隐式地转换为任何指针(包括类的成员函数指针),但不能显式或隐式地转换为任何其他类型。
使用nullptr可以消除这个误会,例如,上面的代码,调用Func(nullptr)一定输出Func(char*)。
其实,C++11将NULL重新定义效果会更好一些,但可能是考虑到已经有太多的代码用了NULL,为了使得以前的代码仍任可用,所以才新增的nullptr吧。
最后,补充一些细节:
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 operator _Tx*() const { return 0; }
template operator _Ty _Tx::*() const{ return 0; }
private:
void operator& () const; // 不允许取地址
};
const nullptr_tt nullptr;