C++11 nullptr:初始化空指針

實際開發中,避免產生“野指針”最有效的方法,就是在定義指針的同時完成初始化操作,即便該指針的指向尚未明確,也要將其初始化爲空指針。

所謂“野指針”,又稱“懸掛指針”,指的是沒有明確指向的指針。野指針往往指向的是那些不可用的內存區域,這就意味着像操作普通指針那樣使用野指針(例如 &p),極可能導致程序發生異常。

C++98/03 標準中,將一個指針初始化爲空指針的方式有 2 種:

int *p = 0;int *p = NULL; //推薦使用

可以看到,我們可以將指針明確指向 0(0x0000 0000)這個內存空間。一方面,明確指針的指向可以避免其成爲野指針;另一方面,大多數操作系統都不允許用戶對地址爲 0 的內存空間執行寫操作,若用戶在程序中嘗試修改其內容,則程序運行會直接報錯。

相比第一種方式,我們更習慣將指針初始化爲 NULL。值得一提的是,NULL 並不是 C++ 的關鍵字,它是 C++ 爲我們事先定義好的一個宏,並且它的值往往就是字面量 0(#define NULL 0)。

C++ 中將 NULL 定義爲字面常量 0,雖然能滿足大部分場景的需要,但個別情況下,它會導致程序的運行和我們的預期不符。例如:



#include <iostream>using namespace std;void isnull(void *c){    cout << "void*c" << endl;}void isnull(int n){    cout << "int n" << endl;}int main() {    isnull(0);    isnull(NULL);    return 0;}

程序執行結果爲:

int n
int n

對於 isnull(0) 來說,顯然它真正調用的是參數爲整形的 isnull() 函數;而對於 isnull(NULL),我們期望它實際調用的是參數爲 void*c 的 isnull() 函數,但觀察程序的執行結果不難看出,並不符合我們的預期。

C++ 98/03 標準中,如果我們想令 isnull(NULL) 實際調用的是 isnull(void* c),就需要對 NULL(或者 0)進行強制類型轉換:

isnull( (void*)NULL );isnull( (void*)0 );

如此,纔會成功調用我們預期的函數(讀者可自行執行此代碼,觀察輸出結果)。

由於 C++ 98 標準使用期間,NULL 已經得到了廣泛的應用,出於兼容性的考慮,C++11 標準並沒有對 NULL 的宏定義做任何修改。爲了修正 C++ 存在的這一 BUG,C++ 標準委員會最終決定另其爐竈,在 C++11 標準中引入一個新關鍵字,即 nullptr

在使用 nullptr 之前,讀者需保證自己使用的編譯器支持該關鍵字。以 Visual Studio 和 codeblocks 爲例,前者早在 2010 版本就對 C++ 11 標準中的部分特性提供了支持,其中就包括 nullptr;如果使用後者,讀者需將其 G++ 編譯器版本至少升級至 4.6.1(同時開啓 -std=c++0x 編譯選項)。

nullptr 是 nullptr_t 類型的右值常量,專用於初始化空類型指針。nullptr_t 是 C++11 新增加的數據類型,可稱爲“指針空值類型”。也就是說,nullpter 僅是該類型的一個實例對象(已經定義好,可以直接使用),如果需要我們完全定義出多個同 nullptr 完全一樣的實例對象。

值得一提的是,nullptr 可以被隱式轉換成任意的指針類型。舉個例子:

int * a1 = nullptr;char * a2 = nullptr;double * a3 = nullptr;

顯然,不同類型的指針變量都可以使用 nullptr 來初始化,編譯器分別將 nullptr 隱式轉換成 int*、char* 以及 double* 指針類型。

另外,通過將指針初始化爲 nullptr,可以很好地解決 NULL 遺留的問題,比如:

#include <iostream>using namespace std;void isnull(void *c){    cout << "void*c" << endl;}void isnull(int n){    cout << "int n" << endl;}int main() {    isnull(NULL);    isnull(nullptr);    return 0;}

程序執行結果爲:

int n
void*c

藉助執行結果不難看出,由於 nullptr 無法隱式轉換爲整形,而可以隱式匹配指針類型,因此執行結果和我們的預期相符。

總之在 C++11 標準下,相比 NULL 和 0,使用 nullptr 初始化空指針可以令我們編寫的程序更加健壯。

圖片


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章