【漫遊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;
相關文章
相關標籤/搜索