- 相对于0或者NULL,优先选用nullptr
- 避免在整型和指针型别之间重载
0和NULL
C++98中,程序员常常采用0或者NULL来判断指针是否为空。在C++11中,我们要采用nullptr来避免不必要的麻烦。
字面常量0的型别是int,而不是一个指针。当C++在只能使用指针的语境中发现了一个0,虽然也会勉强解释为空指针,但是这是个不得已的行为。
以上结论对NULL也成立。虽然标准允许给予NULL非int的型别(比如long),但是不论是0还是NULL,它们都不具备指针型别。
C++的这种基本观点会在指针型别和整形型别发生重载时出现意外:
//三个重载函数
void f(int);
void f(bool);
void f(void*);
f(0); //调用的是f(int),不是f(void*)
f(NULL); //可能不通过编译,但一般会调用f(int),不会调用f(void*)
nullptr
nullptr的优点在于它不具备整型型别。虽然它也不具备指针型别,但是我们可以把它想象成任意一种型别的指针。
nullptr的实际型别是std::nullptr_t。在一个漂亮的循环定义下,std::nullptr_t的定义被指定为nullptr的型别。nullptr_t可以隐式转换到所有裸指针型别,所以nullptr可以扮演所有型别指针。
使用0的时候会调用整型版本的重载函数,而传入nullptr就会调用void*那个重载版本,因为nullptr无法视作任何一种整型:
f(nullptr); //调用的是f(void*)
使用nullptr不仅仅能够避免重载决议的意外,还能够提升代码的清晰性,尤其是使用auto变量的时候。我们阅读代码的时候很容易就能判断出auto变量一定是个指针型别而不是其他型别:
auto result = findRec();
if(result == 0) //不易得出result的型别
{
}
if(result == nullptr) //result必然具备指针型别
{
}
nullptr在有模板的前提下表现最为亮眼。模板中的形参我们要是传入0或者NULL,虽然我们想要表达“我们传入的是空指针”,但型别推导一定会推导出一个int型参数而不是指针型别参数。