C++深入探究用NULL來(lái)初始化空指針是否合適
我們要了解C++11新特性的nullptr,我們很有必要先了解一下C++11之前的程序員是怎么使用空指針的。
1.C++98中的空指針
我們知道,在良好的C/C++編程習(xí)慣中,聲明一個(gè)變量時(shí)最好給這個(gè)變量賦一個(gè)合適的初始值,否則就有可能出現(xiàn)不可預(yù)料的錯(cuò)誤。
指針的危險(xiǎn)性
在C++中創(chuàng)建指針時(shí),計(jì)算機(jī)將分配用來(lái)存儲(chǔ)地址的內(nèi)存,但不會(huì)分配用來(lái)存儲(chǔ)指針?biāo)赶虻牡臄?shù)據(jù)的內(nèi)存。為數(shù)據(jù)提供空間的是一個(gè)獨(dú)立的步驟,忽略這一步無(wú)疑是自找麻煩的,如下所示:
int* fellow; *fellow = 1234;
fellow確實(shí)是一個(gè)指針,但它指向哪里呢?上述代碼沒(méi)有將地址賦給fellow,那么1234將被放置在哪個(gè)內(nèi)存單元呢?我們并不知道。有fellow沒(méi)有被初始化,他可能有任何值。不管值是什么,程序都將他解釋為存儲(chǔ)1234的地址。但是如果fellow的值碰巧為1000,計(jì)算機(jī)將把數(shù)據(jù)放在地址1000上,即使這恰巧是程序代碼的地址,fellow指向的地方很可能并不是所要存儲(chǔ)的1234的地方,這種錯(cuò)誤可能會(huì)導(dǎo)致一些最隱匿,最難以跟蹤的bug。
因此為了避免這個(gè)問(wèn)題,我們都要給指針進(jìn)行初始化。通常我們都是這樣來(lái)初始化指針的。
int main() { //空指針定義 int* p1 = NULL; int* p2 = 0; return 0; }
實(shí)際上NULL是一個(gè)宏,我們?cè)趥鹘y(tǒng)的C頭文件(stddef.h)中就可以看到如下代碼:
可以看到, NULL 可能被定義為字面常量 0 ,或者被定義為無(wú)類型指針 (void*) 的常量 。不論采取何種定義,在使用空值的指針時(shí),都不可避免的會(huì)遇到一些麻煩。 比如:下面這段代碼的輸出結(jié)果是什么?
void f(int) { cout << "f(int)" << endl; } void f(int*) { cout << "f(int*)" << endl; } int main() { //空指針定義 int* p1 = NULL; int* p2 = 0; f(0); f(NULL); return 0; }
按照我們正常的想法f(0)應(yīng)該進(jìn)入void f (int),f(NULL)進(jìn)入void f(int*),因此我們想要得到的結(jié)果是分別打印f(int)和f(int*)。我們來(lái)看運(yùn)行結(jié)果是否和我們所想的一樣。
我們發(fā)現(xiàn)運(yùn)行結(jié)果和我們所想存在出入,這是為什么?
這是因?yàn)槌绦虮疽馐窍胪ㄟ^(guò)f(NULL)調(diào)用指針版本的f(int*)函數(shù),但是由于NULL被宏定義成了0,在預(yù)處理階段,NULL已經(jīng)被宏替換成了0,因此f(NULL)函數(shù)就已經(jīng)被替換成了f(0),因此我們才會(huì)得到兩個(gè)相同的打印結(jié)果。
在 C++98 中,字面常量 0 既可以是一個(gè)整形數(shù)字,也可以是無(wú)類型的指針 (void*) 常量,但是編譯器默認(rèn)情況下將其看成是一個(gè)整形常量,如果要將其按照指針?lè)绞絹?lái)使用,必須對(duì)其進(jìn)行強(qiáng)轉(zhuǎn)(void *)0 。
2.C++11中的空指針
為了避免上述這個(gè)問(wèn)題,C++11引入了nullptr關(guān)鍵字來(lái)表示指針空值。
int main() { //空指針定義 int* p1 = NULL; int* p2 = 0; //推薦 int* p3 = nullptr; f(0); f(NULL); f(nullptr); return 0; }
因此我們?cè)俅蝹魅雗ullptr,看看他的結(jié)果是什么?
此時(shí)我們發(fā)現(xiàn)nullptr解決了這個(gè)問(wèn)題。
注意:
1. 在使用 nullptr 表示指針空值時(shí),不需要包含頭文件,因?yàn)?nullptr 是 C++11 作為新關(guān)鍵字引入的 。
2. 在 C++11 中, sizeof(nullptr) 與 sizeof((void*)0) 所占的字節(jié)數(shù)相同。 在32位機(jī)器下大小為4,在64位下大小為8。
3. 為了提高代碼的健壯性,在后續(xù)表示指針空值時(shí)建議最好使用 nullptr 。
結(jié)論:nullptr是對(duì)NULL的一個(gè)升級(jí),因此在以后的初始化空指針時(shí),建議大家使用nullptr。
到此這篇關(guān)于C++深入探究用NULL來(lái)初始化空指針是否合適的文章就介紹到這了,更多相關(guān)C++ 空指針初始化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++?點(diǎn)(.)和箭頭(->)運(yùn)算符用法小結(jié)
在C++中,點(diǎn)運(yùn)算符(.)用于訪問(wèn)類的成員變量和成員函數(shù),而箭頭運(yùn)算符(->)用于通過(guò)指針訪問(wèn)類的成員變量和成員函數(shù),本文就來(lái)詳細(xì)的介紹一下如何使用,感興趣的可以了解一下2024-01-01C++ 實(shí)戰(zhàn)開(kāi)發(fā)一個(gè)猜單詞的小游戲
眾所周知紙上得來(lái)終覺(jué)淺,我們要在實(shí)戰(zhàn)中才能真正的掌握技術(shù),小編為大家?guī)?lái)一份用C++編寫的猜單詞小游戲,給大家練練手,快來(lái)看看吧2021-11-11C語(yǔ)言基于graphics.h實(shí)現(xiàn)圣誕樹(shù)
這篇文章主要介紹了圣誕樹(shù)代碼,c語(yǔ)言編程,基于graphics.h實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12C++實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)化為后綴表達(dá)式詳解
這篇文章主要為大家詳細(xì)介紹了如何利用C++解決實(shí)現(xiàn)中綴表達(dá)式轉(zhuǎn)換為后綴表達(dá)式的問(wèn)題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03C語(yǔ)言用遞歸函數(shù)對(duì)素?cái)?shù)進(jìn)行判斷流程
素?cái)?shù)判斷是編程語(yǔ)言學(xué)習(xí)過(guò)程中一個(gè)老生常談的話題,而它的實(shí)現(xiàn)也有多種算法,包括經(jīng)典的試除法(以及試除法的幾種優(yōu)化),進(jìn)階的素?cái)?shù)表篩選法,埃拉托斯特尼篩法和歐拉篩法(以及它們的優(yōu)化)等。對(duì)以上算法感興趣的朋友們,不妨搜索“素?cái)?shù)判斷的N種境界”來(lái)學(xué)習(xí)了解2022-09-09