2017-11-11 116 views
2

考慮代碼說明了NULL,0,nullptr

#include <iostream> 

void foo(int* p) 
{ 
    std::cout << "pointer" << '\n'; 
} 

void foo(int p) 
{ 
    std::cout << "value" << '\n'; 
}  

int main() 
{  
    foo(0); // value 
    foo(NULL); // error: call of overloaded ‘foo(NULL)’ is ambiguous foo(NULL); 

    return 0; 
} 

在這裏我們可以看到一個問題,選擇了空指針向右過載,這可以通過傳遞nullptr的功能foo的第二個電話來解決,但我的問題是關於不同的東西......

,因爲我知道大多數實現定義NULL只是一個常量文字0像(#define NULL 0),因此預計在編譯時有第二個呼叫是這樣的 - foo(0)

但預處理器給出了一些奇怪的輸出(運行g++ -std=c++11 -E main.cpp -o main後)

int main() 
{ 

foo(0); 

foo(
# 25 "main.cpp" 3 4 
    __null 
# 25 "main.cpp" 
     ); 

return 0; 
} 

什麼是__null這裏?

這是一個內置的int類型?

+3

看起來像那是特定實現(注意'__')。你正在使用哪種編譯器? – user0042

+0

@ user0042我使用'g ++ 5.4.0' – ampawd

+0

https://gcc.gnu.org/onlinedocs/libstdc++/manual/support.html(最後一段)換句話說,'_null' magic關鍵字應該是準確地阻止你看到的內容(首先將'0'視爲整數,然後將其轉換爲'nullptr')。 – Damon

回答

3

__null是一個內置的編譯器。 GCC使用它來提供更好的診斷。問題是,你真的要定義NULL

#define NULL ((void *) 0) 

- 就像在C.但與當前的C++,你就不能寫

int *p = NULL; 

因爲不像C,沒有暗示從void *轉換爲其他指針類型。所以GCC實現了__null作爲魔術空指針常量,它對於任何指針類型都是有效的,但它不是一個整數。因此,GCC可以發出警告

int a = NULL; 

否則將不可能。

基本上,__nullnullptr的早期版本,但它更保守,因爲它只是一個擴展,而不是語言的改變。