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

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

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

转载于:https://my.oschina.net/jthmath/blog/539845

你可能感兴趣的:(【漫游C++11】nullptr与std::nullptr_t)