對於C/C++的開發者而言,早已習慣了使用NULL,這個用來表示空指針的宏。一直知道它是一個宏定義,其實質就是0,表示不指向任何內存地址的空指針,但卻沒做任何深入思考。
這周由於工作需要在visual studio下做一段開發,在IDE下當我敲完NULL四個字母時,看到了nullptr這個提示詞,這是個什么東西,也是表示空指針么。於是感緊查閱資料。
果然猜的沒錯,這家伙就是表示空指針的,但不同於NULL這個宏定義,nullptr是一個C++關鍵字,從C++11開始引入的,C++11的關鍵字如下圖:
可是,既然有了NULL,為何還要引入nullptr關鍵字呢,於是我們來看一看NULL宏的定義,VC中的NULL定義在vcruntime.h中,
#ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif
在C++中NULL直接定義為0,而在C里,NULL是定義為(void*)0的,這也很好理解,C語言可以隱式轉換,而C++卻是需要顯示的寫出類型轉換的。像int *p = (void *) 0;這樣的語句,在C++里是會報錯的:
error C2440: “初始化”: 無法從“void *”轉換為“int *”
於是在C++中,就干脆直接將NULL定義為0。於是問題就來了,直接定義為0,一個int型的字面量,那么在函數重載時,必定會出現非預期的結果,比如以下這段代碼:
#include <iostream> using namespace std; void func(int a) { cout << "func int" << endl; } void func(char* a) { cout << "func char*" << endl; } int main() { func(NULL); return 0; }
調用處func(NULL)我們可以希望調用的是func(char *a)函數,然而實際上,結果卻是:
將函數調用處改為func(nullptr)試試呢,
結果就對了。看來C++11引入新的關鍵字來解決這個問題還是很有必要的,也因此我們在開發項目中,如果使用的是C++11或以上的標准,還是要多使用新的特性,使用nullptr關鍵字代替NULL宏定義,以免引入一些預想之外的問題,而且這類的問題一旦發生,很難排查。