最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++引用、內(nèi)聯(lián)函數(shù)與nullptr超全解析(新手避坑指南)

 更新時(shí)間:2025年12月12日 09:29:43   作者:say_fall  
這篇文章主要介紹了C++引用、內(nèi)聯(lián)函數(shù)與nullptr的相關(guān)資料,引用提供別名,簡(jiǎn)化代碼和提高性能,內(nèi)聯(lián)函數(shù)通過(guò)減少棧幀開(kāi)銷優(yōu)化性能,但不能濫用,nullptr替代NULL,提供類型安全的空指針表示,需要的朋友可以參考下

前言:

繼命名空間、缺省參數(shù)等基礎(chǔ)內(nèi)容之后,本篇主要講述三個(gè)核心特性:引用、內(nèi)聯(lián)函數(shù)與 nullptr。它們是簡(jiǎn)化代碼結(jié)構(gòu)、優(yōu)化程序性能的重要手段,也是不能輕易理解的知識(shí)點(diǎn),尤其是引用。如何正確使用引用避免權(quán)限問(wèn)題??jī)?nèi)聯(lián)函數(shù)的適用場(chǎng)景是什么?為何推薦用 nullptr 替代 NULL?帶著這些疑問(wèn),本文徹徹底底幫你弄清楚這些概念。

一、 引用

1. 引用基礎(chǔ)

概念:給已有的變量“新名字”(別名)

使用:類型&引?別名=引?對(duì)象;

案例:在需要傳指針的地方,可以用引用代替,不需要調(diào)用該指針,讓形參就叫別名,改變形參就是改變實(shí)參

特性:

  • 引用在定義的時(shí)候必須初始化
  • 一個(gè)變量可以有多個(gè)引用
  • 引用一旦引用一個(gè)實(shí)體,再不能引用其他實(shí)體
int a = 10;
int& ra; // 編譯報(bào)錯(cuò):“ra”: 必須初始化引? 
 
int& b = a;
int c = 20;
// 這?并?讓b引?c,因?yàn)镃++引?不能改變指向, 
// 這?是?個(gè)賦值 

主要應(yīng)用:

  • 函數(shù)參數(shù)傳遞
  • 函數(shù)返回值

引用返回值能不能隨便用?

2. 引用返回注意事項(xiàng):

int& func()
{
int a = 0;
return a;//錯(cuò)的:a是局部的,返回時(shí)候已經(jīng)銷毀,類似野指針
}

int& func1(int& ra)
{
ra = 3
return ra;//對(duì)的:ra是外部傳入的引用,出函數(shù)依舊存在
}

3.const引用規(guī)則:

權(quán)限可縮小不可放大,僅限制引用本身的訪問(wèn)權(quán)限

int main()
{
const int a = 0;
int& ra = a;//錯(cuò)的
const int& ra = a;//對(duì)的
//權(quán)限放大

//注意分辨:
const int a = 0;
int ra = a;//這是可以的,不是權(quán)限放大

int b = 0;
const int& rb = b;//對(duì)的 
//權(quán)限縮小
//這個(gè)地方?jīng)]有縮小b的權(quán)限,b依舊能該改變
b++;//對(duì)
rb++;//錯(cuò)
//類比:公共場(chǎng)合,添加一個(gè)身份,做不了一些事情(權(quán)限縮小)

int& rc = 30;//錯(cuò)
const int& rc = 30;//對(duì)
//const引用可以給常量取別名,單純的引用不可以

//編譯器需要?個(gè)空間暫存表達(dá)式的求值結(jié)果(中間值)時(shí)臨時(shí)創(chuàng)建的?個(gè)未命名的對(duì)象
int rd = (a+b);//可以對(duì)臨時(shí)對(duì)象賦值
int& rd = (a+b);//不可以對(duì)臨時(shí)對(duì)象單純引用(沒(méi)法修改)
const int& rd = (a+b);//可以用const引用(不修改)

double d = 12.34;
int i = d;//是隱式類型轉(zhuǎn)換,這個(gè)過(guò)程有臨時(shí)對(duì)象
int& i = d;//不可以
const int& i = d;//可以

//下面介紹一個(gè)很好用的東西
//函數(shù)模板,T可以是任意類型
template <class T>
void func(T val)
{
//注意看這里傳入的T是任意類型
//所以程序員對(duì)它進(jìn)行一個(gè)引用(&T val)(防止傳入的值太大拷貝成本高)
//這里傳常量/臨時(shí)對(duì)象/帶有類型轉(zhuǎn)換可以嗎?不行
//最終:const &T val,這樣子就什么都能傳
// 使用const引用可接收:
        // 1. 普通變量
        // 2. 常量
        // 3. 臨時(shí)對(duì)象
        // 4. 類型轉(zhuǎn)換結(jié)果
        // 類似void*的通用性
}
return 0;
}

4. 指針和引用的關(guān)系與區(qū)別

  1. 引用不額外開(kāi)空間,指針是開(kāi)一個(gè)空間來(lái)存儲(chǔ)地址
  2. 引用使用必須初始化,指針不是必須要求的
  3. 引用只能初始化一次,不能更改,指針可以更改指向?qū)ο?/li>
  4. 引用可以直接訪問(wèn)對(duì)象(別名),指針需要解引用。
  5. sizeof()引用返回的是引用類型的大小,而指針則根據(jù)操作系統(tǒng)不一樣大小不一樣
  6. 指針有野指針和空指針的問(wèn)題,引用很少有
int* ptr = nullptr;
int& rptr = *ptr;
rptr++;

二、inline 和 宏函數(shù)

1. 宏函數(shù)

  1. 在C語(yǔ)言里有通過(guò)#define定義的宏函數(shù),為了防止,宏函數(shù)的使用往往小心翼翼,要加很多層括號(hào)
  2. 本質(zhì):預(yù)編譯階段的文本替換,不是真正的函數(shù)調(diào)用。
  3. 目的:在避免函數(shù)調(diào)用棧幀開(kāi)銷的同時(shí),實(shí)現(xiàn)代碼復(fù)用(比普通函數(shù)更輕量,比內(nèi)聯(lián)函數(shù)更「強(qiáng)制」替換)。
  4. 展示:
//正確
#define ADD(a,b) ((a)+(b))
int main()
{
	int add = ADD(3,2);
	return 0;
}

//錯(cuò)誤加分號(hào)
#define ADD(a,b) ((a)+(b));
int main()
{
	if (ADD(3, 2) > 0)
	{
		//執(zhí)行某操作
	}
	return 0;
}

#define ADD(a,b) (a+b)
//錯(cuò)誤不加內(nèi)層括號(hào)
int main()
{
	int add = ADD(1 ^ 1, 2 ^ 2);
	//替換以后 =》1^(1+2)^2
	return;
}

#define ADD(a,b) (a)+(b);
//錯(cuò)誤外層無(wú)括號(hào)
int main()
{
	int add = ADD(3,2) * ADD(3,2);
	//替換以后 =》3+(2*3)+2
	return 0;
}

以上是宏函數(shù)的使用

2. inline(內(nèi)聯(lián)函數(shù))

上面宏函數(shù)都二條提到了內(nèi)聯(lián)函數(shù),inline是一個(gè)關(guān)鍵字,他所修飾的函數(shù)稱之為內(nèi)聯(lián)函數(shù),上文提到宏函數(shù)是為減少函數(shù)棧幀的開(kāi)銷,inline也有這個(gè)作用

  • 內(nèi)聯(lián)函數(shù)有什么用?
    內(nèi)聯(lián)函數(shù)是一個(gè)類似”宏函數(shù)“的 函數(shù) ,不同于宏函數(shù),內(nèi)聯(lián)函數(shù)是在函數(shù)內(nèi)部計(jì)算以后返回值,有的朋友要說(shuō):函數(shù)不都這樣嗎?其實(shí)不然,內(nèi)聯(lián)函數(shù)的本質(zhì)是把函數(shù)的獨(dú)立棧幀省略掉,直接使用調(diào)用者的棧幀。
    這里插入棧幀的概念:

棧幀(也叫「活動(dòng)記錄」)是程序運(yùn)行時(shí),棧內(nèi)存中為單個(gè)函數(shù)調(diào)用分配的一塊獨(dú)立內(nèi)存區(qū)域,用于存儲(chǔ)該函數(shù)的:

  • 局部變量
  • 函數(shù)參數(shù)
  • 返回地址(函數(shù)執(zhí)行完后要回到調(diào)用者的哪一行代碼)
  • ?;罚‥BP/RBP 寄存器,用于定位棧幀內(nèi)的變量)
  • 臨時(shí)數(shù)據(jù)(比如表達(dá)式計(jì)算的中間結(jié)果)
  • 程序的調(diào)用棧(Call Stack)就是由多個(gè)嵌套的棧幀組成的,比如 main() 調(diào)用 funcA(),funcA() 又調(diào)用 funcB(),棧中會(huì)依次壓入:main 棧幀 → funcA 棧幀 → funcB 棧幀(棧頂)。

比如說(shuō):在main函數(shù)中調(diào)用一個(gè)inline int add()的函數(shù),如果去掉inline,他會(huì)創(chuàng)建棧幀;而加上inline變?yōu)閮?nèi)聯(lián)函數(shù)以后就在main函數(shù)的棧幀上創(chuàng)建自己的棧幀,省去了跳轉(zhuǎn)等操作,簡(jiǎn)單了許多

當(dāng)函數(shù) A 調(diào)用函數(shù) B 時(shí):

  • 函數(shù) A 是「調(diào)用者(Caller)」,它的棧幀就是「調(diào)用者的棧幀」;
  • 函數(shù) B 是「被調(diào)用者(Callee)」,它的棧幀就是「被調(diào)用者的棧幀」。
    「調(diào)用者的棧幀」就是發(fā)起調(diào)用的那個(gè)函數(shù)在棧上的內(nèi)存區(qū)域,在函數(shù)調(diào)用過(guò)程中,它會(huì)暫時(shí)被「被調(diào)用者的棧幀」覆蓋(棧頂偏移),但調(diào)用結(jié)束后,CPU 會(huì)回到調(diào)用者的棧幀繼續(xù)執(zhí)行。

那內(nèi)聯(lián)函數(shù)好處這么多,能不能所有函數(shù)都直接前面加inline使其變成內(nèi)聯(lián)函數(shù)呢?

答案是 不可以 ,因?yàn)閮?nèi)聯(lián)函數(shù)還是在調(diào)用者的內(nèi)部把函數(shù)展開(kāi)了,有點(diǎn)類似與你沒(méi)有使用函數(shù),而是直接給函數(shù)內(nèi)部的代碼 粘貼 到了原函數(shù)處,這大大增加了可執(zhí)行文件的內(nèi)存占用量。

除此之外,內(nèi)聯(lián)函數(shù)還有很重要的一個(gè)缺點(diǎn):聲明和定義不能分離在兩個(gè)文件中,會(huì)導(dǎo)致鏈接失敗。
值得注意的一點(diǎn)是,在有些編譯器(如vs2022)中,并非程序員添加inline他就變成了內(nèi)聯(lián)函數(shù),這得編譯器的心情(其實(shí)就是debug下,編譯器會(huì)識(shí)別內(nèi)聯(lián)函數(shù)的代碼量,如果代碼量很大,就不會(huì)展開(kāi)函數(shù),而是作為一般函數(shù)調(diào)用)

如果想要調(diào)試的話,按照下方的操作可以在debug模式下調(diào)試:

  • 菜單欄 - 項(xiàng)目 - 屬性

三、 nullptr

NULL實(shí)際是?個(gè)宏,在傳統(tǒng)的C頭?件(stddef.h)中,可以看到如下代碼:

#ifndef NULL
 	#ifdef __cplusplus
 		#define NULL 0
 	#else
 		#define NULL ((void *)0)
 	#endif
#endif
  • 也就是說(shuō),在C++里面NULL,被定義為了0,是一個(gè)int類型。
  • C++11中引?nullptr,nullptr是?個(gè)特殊的關(guān)鍵字,nullptr是?種特殊類型的字?量,它可以轉(zhuǎn)換成任意其他類型的指針類型。使?nullptr定義空指針可以避免類型轉(zhuǎn)換的問(wèn)題,因?yàn)?code>nullptr只能被隱式地轉(zhuǎn)換為指針類型,?不能被轉(zhuǎn)換為整數(shù)類型。

從此以后,C++里面的空指針使用nullptr,不使用NULL。

總結(jié) 

到此這篇關(guān)于C++引用、內(nèi)聯(lián)函數(shù)與nullptr的文章就介紹到這了,更多相關(guān)C++引用、內(nèi)聯(lián)函數(shù)與nullptr內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C++使用opencv讀取圖片的操作代碼(圖像處理)

    C++使用opencv讀取圖片的操作代碼(圖像處理)

    這篇文章主要介紹了C++使用opencv讀取圖片,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C++內(nèi)存管理面經(jīng)

    C++內(nèi)存管理面經(jīng)

    這篇文章主要介紹了C++的內(nèi)存分配方式以及介紹了下棧和堆的區(qū)別,感興趣的小伙伴可以參考閱讀本文
    2023-03-03
  • C++深入淺出講解函數(shù)重載

    C++深入淺出講解函數(shù)重載

    C++允許多個(gè)函數(shù)擁有相同的名字,只要它們的參數(shù)列表不同就可以,這就是函數(shù)的重載(Function?Overloading),借助重載,一個(gè)函數(shù)名可以有多種用途
    2022-05-05
  • 淺談C語(yǔ)言中的sizeof()和strlen()的區(qū)別

    淺談C語(yǔ)言中的sizeof()和strlen()的區(qū)別

    本文主要介紹了C語(yǔ)言中的sizeof()和strlen()的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++?Qt開(kāi)發(fā)之使用QUdpSocket實(shí)現(xiàn)UDP網(wǎng)絡(luò)通信

    C++?Qt開(kāi)發(fā)之使用QUdpSocket實(shí)現(xiàn)UDP網(wǎng)絡(luò)通信

    Qt 是一個(gè)跨平臺(tái)C++圖形界面開(kāi)發(fā)庫(kù),利用Qt可以快速開(kāi)發(fā)跨平臺(tái)窗體應(yīng)用程序,本文主要介紹如何運(yùn)用QUdpSocket組件實(shí)現(xiàn)基于UDP的網(wǎng)絡(luò)通信功能,需要的可以參考下
    2024-03-03
  • C++中vector的模擬實(shí)現(xiàn)實(shí)例詳解

    C++中vector的模擬實(shí)現(xiàn)實(shí)例詳解

    vector是表示可變大小數(shù)組的序列容器,它也采用連續(xù)存儲(chǔ)空間來(lái)存儲(chǔ)元素,因此可以采用下標(biāo)對(duì)vector的元素進(jìn)行訪問(wèn),這篇文章主要給大家介紹了關(guān)于C++中vector模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 利用C語(yǔ)言實(shí)現(xiàn)三子棋(井字棋)小游戲

    利用C語(yǔ)言實(shí)現(xiàn)三子棋(井字棋)小游戲

    這篇文章主要為大家詳細(xì)介紹了利用C語(yǔ)言實(shí)現(xiàn)三子棋小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 從C語(yǔ)言中讀取Python 類文件對(duì)象

    從C語(yǔ)言中讀取Python 類文件對(duì)象

    這篇文章主要介紹了如何從C語(yǔ)言中讀取Python 類文件對(duì)象,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • C++利用socket傳輸大文件的實(shí)現(xiàn)代碼

    C++利用socket傳輸大文件的實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了C/C++如何使用socket傳輸大文件的實(shí)現(xiàn)代碼,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下
    2023-10-10
  • C語(yǔ)言實(shí)現(xiàn)散列表(哈希Hash表)實(shí)例詳解

    C語(yǔ)言實(shí)現(xiàn)散列表(哈希Hash表)實(shí)例詳解

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)散列表(哈希Hash表)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評(píng)論

遂溪县| 化德县| 石家庄市| 扎赉特旗| 屏东市| 长宁县| 珠海市| 富宁县| 五家渠市| 镇平县| 句容市| 石泉县| 大厂| 革吉县| 上饶县| 甘德县| 天祝| 潢川县| 潼南县| 高青县| 邵东县| 桐梓县| 鄯善县| 乃东县| 尖扎县| 华蓥市| 盖州市| 深泽县| 麻栗坡县| 博客| 阿拉尔市| 台湾省| 连南| 鹿邑县| 渭源县| 江川县| 万荣县| 临西县| 合阳县| 濉溪县| 瑞丽市|