日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

空指针:从 0 到 NULL,再到 nullptr

發(fā)布時間:2024/4/18 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 空指针:从 0 到 NULL,再到 nullptr 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

nullptr

空指針:從 0 到 NULL,再到 nullptr

NULL 是一個宏定義:

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

?

int *my_ptr = 0; int *my_ptr = NULL; // NULL 的問題 #include <stdio.h>void f(char *c) {printf("invoke f(char *)\n); } void f(int i) {printf("invoke f(int)\n"); } int main() {f(0);f(NULL); // 注意:如果gcc編譯,NULL會轉(zhuǎn)換為內(nèi)部標(biāo)識符 __null,該語句會編譯失敗f((char*)0); } /** 使用 XLC 編譯器會得到如下結(jié)果:* invoke f(int)* invoke f(int)* invoke f(char*)* XLC 將 NULL 定義為了 0 */

引起該問題的原因是 0 的二義性。0 既可以表示整型,也可以表示一個 空指針(void *)。存在二義性時,需要使用強制類型轉(zhuǎn)換:((void *)0).

雖然 g++ 編譯器將 NULL 轉(zhuǎn)換為編譯器內(nèi)部標(biāo)識符(__null),并在編譯時期進(jìn)行了分析,在一定程度上可以緩解問題,但是會帶來代碼移植的限制。

?

nullptr

// 頭文件: cstddef typedef decltype(nullptr) nullptr_t; /*使用 nullptr_t 必須包含頭文件: cstddef。使用 nullptr 則不需要 */

nullptr 最大的優(yōu)勢是 有類型,且可以被隱式轉(zhuǎn)換為指針類型。

#include <stdio.h>void f(char *c) {printf("invoke f(char *)\n); } void f(int i) {printf("invoke f(int)\n"); } int main() {f(nullptr); // invoke f(char *)f(0); // invoke f(int) }

nullptr 和 nullptr_t

C++11 不僅定義了空指針常量 nullptr,也定義了 空指針類型 nullptr_t。那么也就是說 nullptr_t 可以用來定義變量。通常,可以使用 nullptr_t 聲明一個 空指針變量。

  • C++11規(guī)定:
    • 所有定義為 nullptr_t 類型的數(shù)據(jù)都是等價的,行為也是完全一致。
    • nullptr_t 類型數(shù)據(jù)可以隱式轉(zhuǎn)換為任意一個指針類型。
    • nullptr_t 類型數(shù)據(jù)不能轉(zhuǎn)化為 非指針類型,即使使用 reinterpret_cast<nullptr_t>()。
    • nullptr_t 類型數(shù)據(jù)不適用于算術(shù)運算表達(dá)式。
    • nullptr_t 類型數(shù)據(jù)可以用于關(guān)系運算表達(dá)式,但僅能與 nullptr_t 類型數(shù)據(jù)或指針類型數(shù)據(jù)做比較,當(dāng)且僅當(dāng)關(guān)系運算符為 ==, <=, >=時返回 true.
#include <iostream> #include <typeinfo> using namespace std; int main() {// nullptr 可以隱式轉(zhuǎn)換為 char*char *cp = nullptr;// 不可轉(zhuǎn)換為整型,而其他類型也不能轉(zhuǎn)換為 nullptr_t// int n1 = nullptr;// int n2 = reinterpret_cast<int>(nullptr);// nullptr 與 nullptr_t 類型變量可以比較// 當(dāng)使用 ==, <=, >= 符號比較時返回 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 nptr < nullptr" << endl;} else {cout << "nullptr_t nptr !< nullptr" << endl; }// 不能轉(zhuǎn)換為整型或 bool 類型// if (0 == nullptr);// if (nullptr);// 不可以進(jìn)行算術(shù)運算// nullptr += 1;// nullptr * 5;// 以下操作均可以正常運行sizeof(nullptr);typeid(nullptr);throw(nullptr);return 0; }

雖然 nullptr_t 看起來像是一個 指針類型,但是在把 nullptr_t 應(yīng)用于模板時,我們發(fā)現(xiàn)模板卻只能把他作為一個普通的類型來推導(dǎo)。(并不會將其視為 T* 指針)

using namespace std; template<typename T> void g(T* t) {} template<typename T> void h(T t) {}int main() {g(nullptr); // error,nullptr 時 nullptr_t 類型,而不是指針g((float*)nullptr); // T = floath(0); // T = inth(nullptr); // T = nullptr_th((float*)nullptr); // T = float *}

一些關(guān)于 nullptr 規(guī)則的討論

  • sizeof(nullptr_t) == sizeof(void *)

  • nullptr 是一個編譯時期的常量,它的名字是一個編譯時期的關(guān)鍵字,能夠為編譯器識別。

  • (void *)0 只是一個強制轉(zhuǎn)換表達(dá)式,其返回的也是一個 void * 指針類型

  • nullptr 到任何指針的轉(zhuǎn)換都是隱式的。

  • nullptr 對象的地址可以被用戶使用

#include <cstdio> #include <cstddef> using namespace std; int main() {nullptr_t my_null;printf("%x\n", &my_null);// printf("%x", &nullptr); // 根據(jù) C++11 的規(guī)定,nullptr 是右值常量,無法取地址printf("%d\n", my_null == nullptr);const nullptr_t && default_nullptr = nullptr;// default_nullptr 是 nullptr 的一個右值引用printf("%x\n", &default_nullptr); }



?

總結(jié)

以上是生活随笔為你收集整理的空指针:从 0 到 NULL,再到 nullptr的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。