C++ nullptr 與 NULL 的差異

本篇 ShengYu 介紹 C++11 nullptr 與 NULL 的差異,nullptr 是 C++11 加入的新功能,用法跟 NULL 差不多,那為什麼 C++11 要生出一個 nullptr 呢?nullptr 跟原本的 NULL 又有什麼差別?欲知詳情請慢慢聽我說來~~~

在 C++ 裡用 NULL 會遇上什麼麻煩?

以前我在寫函數重載時遇到了編譯錯誤,程式如下,

cpp-nullptr.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// g++ cpp-nullptr.cpp -o a.out
#include <iostream>
using namespace std;

void myprint(char* p) {
std::cout << "pointer\n";
}

void myprint(int n) {
std::cout << "integer\n";
}

int main() {
myprint(0);
myprint(NULL); // compile error
return 0;
}

現代聰明的編譯器告訴我 myprint(NULL) 這個寫法模糊不清,編譯器它搞不清楚要呼叫誰,它不知道是整數0還是null pointer,在多載時可能會選擇了錯誤的函式來呼叫,

1
2
3
4
5
6
7
8
9
10
cpp-nullptr.cpp: In function ‘int main()’:
cpp-nullptr.cpp:15:17: error: call of overloaded ‘myprint(NULL)’ is ambiguous
myprint(NULL); // compile error
^
cpp-nullptr.cpp:5:6: note: candidate: void myprint(char*)
void myprint(char* p) {
^
cpp-nullptr.cpp:9:6: note: candidate: void myprint(int)
void myprint(int n) {
^

在沒有 C++11 前時怎麼解決這問題?

在沒有 C++11 前,如果我硬要呼叫到 myprint(char* p) 該怎麼作?
你可以直接強制轉型成 char *,這樣就會指定呼叫到 myprint(char* p)

cpp-nullptr2.cpp
1
myprint((char *)NULL)

或者使用 static_cast,像這樣

cpp-nullptr2.cpp
1
myprint(static_cast<char *>(NULL));

但是這樣的寫法閱讀性差,還是沒有很好地區分整數0還是null pointer,
所以 C++ 中的 NULL 是什麼?

C 的 NULL 是什麼?C++ 的 NULL 又是什麼?

你可以在 stddef.h 標頭檔中找到這樣的定義,
如果程式是 C++ 的話 ifdef __cplusplus 會成立,NULL 就定義成 0
否則定義成 void *,而在 C 語言中 NULL 被定義為 void *

也就是說 C++ 中的 NULL 就是 0,

stddef.h
1
2
3
4
5
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif

喔喔~原來如此呀!

C++11 的 nullptr 解決什麼問題?

nullptr 出現解決上述討論的問題,nullptr 指的就是 null pointer,nullptr 可以視為指向所有型別的指標,不會再跟整數0搞混,nullptr 實際類型是 std::nullptr_t 定義在 c++config.h 裡,

c++config.h
1
2
3
#if __cplusplus >= 201103L
typedef decltype(nullptr) nullptr_t;
#endif

所以這邊試著改用 nullptr 來解決剛剛的問題吧!

cpp-nullptr3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// g++ cpp-nullptr3.cpp -o a.out -std=c++11
#include <iostream>
using namespace std;

void myprint(char* p) {
std::cout << "pointer\n";
}

void myprint(int n) {
std::cout << "integer\n";
}

int main() {
myprint(0);
myprint(nullptr);
return 0;
}

程式輸出如下,成功的執行~~~而且明確!

1
2
integer
pointer

説穿了 nullptr 無非就是要改進原本 NULL 的缺點,丟棄使用 NULL,
在 Scott Meyers 大神的《Effective Modern C++》書裡的條款 8 也提到:「需要使用空指標就該使用 nullptr 而不是 0 或 NULL」。
好啦!以上就是 ShengYu 的經驗,希望透過這經驗讓你們了解 nullptr 與 NULL 的差異,

以上就是 C++ nullptr 與 NULL 的差異介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其他參考
C++11 - 維基百科,自由的百科全書
https://zh.wikipedia.org/zh-tw/C%2B%2B11#%E7%A9%BA%E6%8C%87%E6%A8%99
nullptr in C++11 | 打字猴
https://coherence0815.wordpress.com/2015/08/24/nullptr-in-c11/
史上最明白的NULL、0、nullptr 區別分析(老師講N篇都沒講明白的東東),今天終於明白了,如果和我一樣以前不明白的可以好好的看看…
https://www.cnblogs.com/porter/p/3611718.html
为什么建议你用nullptr而不是NULL | 守望的个人博客
https://www.yanbinghu.com/2019/08/25/36794.html
C/C++杂记:NULL与0的区别、nullptr的来历 - malecrab - 博客园
https://www.cnblogs.com/malecrab/p/5569707.html
C++11標準之NULL與nullptr比較
https://blog.csdn.net/liubing8609/article/details/87644289
C 語言常見誤解/指標/空指標與NULL
https://zh.m.wikibooks.org/zh-hant/C_%E8%AA%9E%E8%A8%80%E5%B8%B8%E8%A6%8B%E8%AA%A4%E8%A7%A3/%E6%8C%87%E6%A8%99/%E7%A9%BA%E6%8C%87%E6%A8%99%E8%88%87NULL

其它相關文章推薦
C/C++ 新手入門教學懶人包
C/C++ 字串轉數字的4種方法
C++ virtual 的兩種用法
C/C++ 字串反轉 reverse
C/C++ call by value傳值, call by pointer傳址, call by reference傳參考 的差別
C++ 類別樣板 class template
std::sort 用法與範例
std::find 用法與範例
std::queue 用法與範例
std::map 用法與範例
std::deque 用法與範例
std::vector 用法與範例