C++中的引用和inline 和 nullptr全面解析
一.引用
1.1引用的概念與定義
引?不是新定義?個(gè)變量,?是給已存在變量取了?個(gè)別名,編譯器不會(huì)為引?變量開辟內(nèi)存空間, 它和它引?的變量共?同?塊內(nèi)存空間。?如:?壺傳中李逵,宋江叫"鐵?",江湖上?稱"?旋 ?";林沖,外號(hào)豹?頭;
類型& 引?別名=引?對(duì)象
C++中為了避免引?太多的運(yùn)算符,會(huì)復(fù)?C語?的?些符號(hào),?如前?的>,這?引?也和取 地址使?了同?個(gè)符號(hào)&,?家注意使??法?度區(qū)分就可以。(吐槽?下,這個(gè)問題其實(shí)挺坑的,個(gè) ?覺得?更多符號(hào)反?更好,不容易混淆

從這里我們可以看出,i和j的地址是一樣的,說明他們指向同一塊空間,引用不會(huì)開辟新空間

1.2 引?的特性
1.引?在定義時(shí)必須初始化
2.?個(gè)變量可以有多個(gè)引?

3. 引??旦引??個(gè)實(shí)體,再不能引?其他實(shí)體

這里我們可以看出,引用b指向了a,說明是給a取了別名;若要讓b在指向d,d現(xiàn)在是20,這里就是賦值的意思,將20賦值給b,而b又是a的別名,所以a的值也發(fā)生了改變
4.別名++,其存在的變量也++

1.3 引?的使?
1.3.1引用傳參的使用
1. 引?在實(shí)踐中主要是于引?傳參和引?做返回值中減少拷?提?效率和改變引?對(duì)象時(shí)同時(shí)改變被引?對(duì)象。
2.引?傳參跟指針傳參功能是類似的,引?傳參相對(duì)更?便?些。


如果使用指針來實(shí)現(xiàn)兩個(gè)數(shù)的交換,首先Swap1中的ab需要開辟一個(gè)空間來指向x1,y1的地址,需要拷貝;
若用引用的話,只是給x2,y2起別名,ab發(fā)生改變,x2,y2也同時(shí)發(fā)生改變,但這種情況不會(huì)開辟新空間,不需要拷貝優(yōu)于指針




上面的圖返回的是臨時(shí)變量,是一個(gè)值,需要存儲(chǔ)起來,不能直接進(jìn)行修改;
下面的圖返回的是它的引用,可以進(jìn)行直接修改
3.引?返回值的場景相對(duì)?較復(fù)雜,我們在這?簡單講了?下場景,還有?些內(nèi)容后續(xù)類和對(duì)象章節(jié) 中會(huì)繼續(xù)深?講解。
4.引?和指針在實(shí)踐中相輔相成,功能有重疊性,但是各有特點(diǎn),互相不可替代。C++的引?跟其他 語?的引?(如Java)是有很?的區(qū)別的,除了?法,最?的點(diǎn),C++引?定義后不能改變指向, Java的引?可以改變指向。
5.?些主要?C代碼實(shí)現(xiàn)版本數(shù)據(jù)結(jié)構(gòu)教材中,使?C++引?替代指針傳參,?的是簡化程序,避開 復(fù)雜的指針,但是很多同學(xué)沒學(xué)過引?,導(dǎo)致?頭霧?。
1.3.2傳引用返回
再說傳引用返回,這里返回的是ret的別名


但是這樣的傳引用返回的行為,本質(zhì)上是非常危險(xiǎn)的,func函數(shù)結(jié)束之后,func棧幀就銷毀了,但是tmp依舊是ret這塊空間的別名,tmp依舊在訪問ret,就相當(dāng)于野指針的訪問。此時(shí)返回的就不一定是0了,也有可能是隨機(jī)值
正確傳引用返回:
如圖出了作用域,func1結(jié)束,ret還在,此時(shí)被static修飾的ret就不存在func1的棧幀之中了

1.4 const引用
1.可以引用一個(gè)const對(duì)象,但是必須用const引用。const引用也可以引用普通對(duì)象,因?yàn)閷?duì)象的訪問權(quán)限在引用過程中可以縮小,但是不能放大。
如圖,如果a被const修飾了,引用就不能使用了,此時(shí)a不能改變,但是b是a的別名,可以改變a,這就是一個(gè)權(quán)限放大的場景,權(quán)限是不能放大的,想要正常引用就要權(quán)限移b也要被const修飾

用const修飾a,a只能讀不能寫;而b是a的引用,沒有用const,那么b既能讀又能寫,放大了a的權(quán)限

這樣寫才是正確的,a和b都只能讀不能寫。

a可讀可寫,但是引用后只能讀不能寫,這樣是正確的,縮小了權(quán)限
2.不需要注意的是類似 int& rb = a*3; double d = 12.34; int& rd = d; 這樣?些場 景下a*3的和結(jié)果保存在?個(gè)臨時(shí)對(duì)象中, int& rd = d 也是類似,在類型轉(zhuǎn)換中會(huì)產(chǎn)?臨時(shí)對(duì) 象存儲(chǔ)中間值,也就是說,rb和rd引?的都是臨時(shí)對(duì)象,?C++規(guī)定臨時(shí)對(duì)象具有常性,所以這? 就觸發(fā)了權(quán)限放?,必須要?常引?才可以。

int&是非常量左值引用,它只能綁定到一個(gè)可修改的左值(即有內(nèi)存地址的變量)。a * 3是一個(gè)臨時(shí)右值(計(jì)算結(jié)果是一個(gè)沒有名字的臨時(shí)值,沒有持久的內(nèi)存地址),無法被非常量左值引用綁定。
正確寫法是在引用前面加上const修飾,只能讀。

double d = 12.34;定義了一個(gè)double類型變量d,值為12.34。int i = d;- 將
double類型的d隱式轉(zhuǎn)換為int,截?cái)嘈?shù)部分,i的值為12。 - 這是直接賦值,
i是一個(gè)獨(dú)立的新變量,和d共享內(nèi)存。
- 將
const int& ri = d;- 試圖將
double類型的d綁定到const int&類型的引用。 - 由于類型不匹配,編譯器會(huì)生成一個(gè)臨時(shí)的
int類型對(duì)象,將d截?cái)酁?12存入該臨時(shí)對(duì)象,然后讓ri綁定到這個(gè)臨時(shí)對(duì)象。 - 這就是圖中標(biāo)注的「臨時(shí)對(duì)象」:它是一個(gè)匿名的、生命周期被
const int&延長的臨時(shí)變量,ri并不直接引用d,而是引用這個(gè)臨時(shí)對(duì)象。
- 試圖將
1.5指針與引用的關(guān)系
| 對(duì)比維度 | 引用(Reference) | 指針(Pointer) |
|---|---|---|
| 本質(zhì)概念 | 變量的別名,不單獨(dú)占用內(nèi)存空間 | 存儲(chǔ)變量的內(nèi)存地址,需要占用內(nèi)存空間 |
| 初始化要求 | 定義時(shí)必須初始化,且必須綁定到一個(gè)已存在的對(duì)象 | 建議初始化,但語法上不強(qiáng)制,可以先聲明后賦值 |
| 指向關(guān)系 | 初始化后無法再更改綁定對(duì)象,始終指向最初綁定的變量 | 可以隨時(shí)改變指向,指向不同的變量或空地址 |
| 訪問方式 | 直接使用引用名訪問目標(biāo)對(duì)象,無需解引用 | 需要通過 * 解引用操作符才能訪問目標(biāo)對(duì)象 |
| sizeof 含義 | sizeof(引用) 結(jié)果為所引用類型的大小(如 sizeof(int&) = 4) | sizeof(指針) 結(jié)果為地址空間的字節(jié)數(shù)(32 位平臺(tái)為 4 字節(jié),64 位平臺(tái)為 8 字節(jié)) |
| 安全性 | 不存在空引用、野引用問題,使用相對(duì)更安全 | 容易出現(xiàn)空指針、野指針問題,使用時(shí)需額外判斷合法性 |
| 典型用途 | 函數(shù)參數(shù)傳遞(避免拷貝)、函數(shù)返回值(保證非空) | 動(dòng)態(tài)內(nèi)存管理、數(shù)組遍歷、復(fù)雜數(shù)據(jù)結(jié)構(gòu)(鏈表 / 樹)的節(jié)點(diǎn)操作 |
二、inline
先看一下宏常見的問題



看似沒有問題,但這個(gè)宏在另一種場景下就又不對(duì)了

所以可以看出宏函數(shù)很容易出現(xiàn)問題,很復(fù)雜,還不能調(diào)試
所以C++之父就搞了個(gè)內(nèi)聯(lián)出來
寫個(gè)函數(shù)是不容易寫錯(cuò)的,但寫個(gè)宏函數(shù)很容易寫錯(cuò)
宏函數(shù)的優(yōu)點(diǎn)就是可以提高效率,適用于高頻調(diào)用的小函數(shù),預(yù)處理階段宏會(huì)替換,不建立棧幀,而且宏甚至可以傳類型
C++中內(nèi)聯(lián)就是用來替換宏的
用inline修飾的函數(shù)叫做內(nèi)聯(lián)函數(shù),編譯時(shí)C++編譯器會(huì)在調(diào)用的時(shí)候展開(不是把函數(shù)部分的代碼直接放到主函數(shù)處,而是把函數(shù)地方的邏輯經(jīng)過一定的處理,經(jīng)過編譯器自己分析,用于主函數(shù)處)內(nèi)聯(lián)函數(shù),這樣調(diào)用內(nèi)聯(lián)函數(shù)就不需要建立棧幀了,就可以提高效率
inline對(duì)于編譯器而言只是一個(gè)建議,也就是說,你加了inline編譯器也可以選擇在調(diào)用的地方不展開,不同編譯器關(guān)于inline什么情況展開各不相同,因?yàn)镃++標(biāo)準(zhǔn)沒有規(guī)定這個(gè)。inline適用于頻繁調(diào)用的短小函數(shù),對(duì)于遞歸函數(shù),代碼相對(duì)多一些的函數(shù),加上inline也會(huì)被編譯器忽略。

三、nullptr
nullptr是C++11的一個(gè)關(guān)鍵字,是用來替代C語言的NULL的
NULL實(shí)際上是一個(gè)宏,在傳統(tǒng)的C頭文件(stddef.h)中,可以看到如下代碼:
#ifndef NULL
#ifdef __cplusplus
//C++中的NULL被替換為0,默認(rèn)為整型
#define NULL 0
#else
//C語言中的NULL也被替換為0,但是被強(qiáng)制類型轉(zhuǎn)換為(void*)
#define NULL ((void *)0)
#endif
#endifC++中NULL可能被定義為字面常量0,或者C中被定義為無類型指針(void * )的常量。不論采取何種定義,在使用空值的指針時(shí),都不可避免的會(huì)遇到一些麻煩,本想通過f(NULL)調(diào)用指針版本的f(int * )函數(shù),但是由于NULL被定義成0,調(diào)用了f(int x),因此與程序的初衷相悖。f((void* )NULL);調(diào)用會(huì)報(bào)錯(cuò)


在C++之中,void* 給int* 是需要強(qiáng)制類型轉(zhuǎn)換的
C++11中引用nullptr,nullptr是一個(gè)特殊的關(guān)鍵字(就相當(dāng)于語法層在編譯的時(shí)候就特殊解決該問題了),nullptr是一種特殊類型的字面量,它可以轉(zhuǎn)換成任意其它類型的指針類型(值還為0)。使用nullptr定義空指針可以避免類型轉(zhuǎn)換的問題,因?yàn)閚ullptr只能被隱式轉(zhuǎn)換為指針類型,而不能被轉(zhuǎn)換為整數(shù)類型。

到此這篇關(guān)于C++中的引用和inline 和 nullptr全面解析的文章就介紹到這了,更多相關(guān)C++引用和inline 和 nullptr內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++17 使用 std::string_view避免字符串拷貝優(yōu)化程序性能
這篇文章主要介紹了C++17 使用 std::string_view避免字符串拷貝優(yōu)化程序性能,幫助大家提高程序運(yùn)行速度,感興趣的朋友可以了解下2020-10-10
C++?std::copy與memcpy區(qū)別小結(jié)
本文主要介紹了C++?std::copy與memcpy區(qū)別小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
C語言實(shí)現(xiàn)手寫Map(全功能)的示例代碼
這篇文章主要為大家詳細(xì)介紹了如何利用C語言實(shí)現(xiàn)手寫Map(全功能),文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語言有一定幫助,需要的可以參考一下2022-08-08
C++類模板實(shí)戰(zhàn)之vector容器的實(shí)現(xiàn)
本文我們將做一個(gè)類模板實(shí)戰(zhàn)-手寫精簡版vector容器。讓我們自己封裝一個(gè)數(shù)組類,可以適應(yīng)基本數(shù)據(jù)類型和自定義數(shù)據(jù)類型,感興趣的可以了解一下2022-07-07
Qt編寫提示進(jìn)度條的實(shí)現(xiàn)示例
進(jìn)度條在很地方都可以使用到,Qt自帶的進(jìn)度條或者操作系統(tǒng)的進(jìn)度條樣式,不夠炫,本文就介紹一下Qt編寫自定義控件的提示進(jìn)度條的實(shí)現(xiàn)示例,感興趣的可以了解一下2021-12-12
C++實(shí)現(xiàn)LeetCode(100.判斷相同樹)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(100.判斷相同樹),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07

