C++11 nullptr與nullptr_t


  參考《深入理解C++11》

  NULL是一個宏定義,在傳統C頭文件stddef.h中定義如下:

#undef NULL
#ifdef(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif

  可以看到,NULL可能被定義為字面常量0,或者定義為無類型指針(void*)常量。這就使得在使用NULL時有些問題:

 

   在main函數中,f(NULL)調用的起始是第二個函數,因為在C++98中,字面常量0具有二義性:既可以是一個整型,也可以是一個無類型指針(void*)。如果想要調用f(char*)的話,需要對字面常量0進行強制類型轉換:(void*)0 然后再調用,否則編譯器總會優先把0看做一個整型常量。

nullptr_t的定義:頭文件:<cstddef>

  typedef decltype(nullptr) nullptr_t;

  使用nullptr_t時必須包含頭文件:<cstddef>,但是使用nullptr時則不用,因為nullptr是關鍵字。nullptr是有類型的,且僅可以被隱式轉化為指針類型,在編寫C++11代碼時,使用nullptr替換NULL將使得代碼更健壯。

  • nullptr:指針空值常量
  • nullptr_t:指針空值類型,也就是nullptr的類型,見上面的定義

nullptr_t注意事項:

 

 示例代碼:

    char* cp = nullptr;

    //不可轉換為整型,而任何類型也不能轉換為nullptr_t
    //以下代碼不能通過編譯
    //int n1 = nullptr;
    //int n2 = reinterpret_cast<int>(nullptr);

    //nullptr與nullptr_t類型變量可以作比較
    //當使用 ==  <=  >=符號比較時返回true
    nullptr_t nptr;
    if (nptr == nullptr)
    {
        cout << "nullptr_t nptr == nullptr" << endl;
    }
    else
    {
        cout << "nullptr_t nptr != nullptr" << endl;
    }
    if (nptr < nullptr)
        cout << "nullptr_t nptr < nullptr" << endl;
    else
        cout << "nullptr_t nptr !< nullptr" << endl;

    //不能轉換為整型或bool類型,以下代碼不能通過編譯
    //if(0 == nullptr)
    //if(nullptr)

    //不能進行算術運算,以下代碼不能通過編譯
    //nullptr += 1;
    //nullptr *5;

    //以下操作均可正常運行
    size_t size1 = sizeof(nullptr);
    typeid(nullptr);
    throw(nullptr);

注:如果上述代碼注釋部分能通過編譯,可能是編譯器版本不夠新,在C++11中不允許上述注釋代碼。

   雖然nullptr_t看起來像是個指針類型,但是在把nullptr_t應用於模板中時,模板會把它作為一個普通的類型來進行推導,並不會將其視為T*指針。

template<typename T>
void g(T* t){}

template<typename T>
void h(T t){}

int main(int argc, char *argv[])
{
    g(nullptr);         //編譯失敗,nullptr的類型是nullptr_t,而不是指針
    g((float*) nullptr);//推導出T=float

    h(0);               //推導出T=int
    h(nullptr);         //推導出T=nullptr_t
    h((float*)nullptr); //推導出T=float*
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM