【漫游C++11】nullptr与std::nullptr_t

在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;
相关文章
相关标签/搜索