c++左值引用和右值引用 2024-02-25

C++工程代碼中經(jīng)常會(huì)看見(jiàn)這樣的函數(shù)入?yún)ⅲ?/p>

void fun(int & a, int* b){
  ...
  return;
}

上面的函數(shù)使用了引用作為函數(shù)的入?yún)ⅲ?/p>

左值引用和右值引用

有時(shí)候還會(huì)見(jiàn)到更加奇怪的變量定義:

int a = 10;
int &b = a;
int &&c = 10; 

上面代碼內(nèi)b就是左值引用了,而c就是右值引用;

c++左值與右值

int a = 10;

c++代碼原本就有左值和右值之分,其中上面代碼第一行變量a就是左值,而數(shù)字10就是右值看峻;
一般來(lái)說(shuō)左值在內(nèi)存中是有分配空間的,而右值很有可能因?yàn)橹皇侵虚g量,可能只存在cpu某個(gè)寄存器內(nèi)而沒(méi)有具體內(nèi)存地址侄旬;
簡(jiǎn)單來(lái)說(shuō),在‘=’左邊的是左值煌妈,而在‘=’右邊的就是右值儡羔。

回到引用的說(shuō)明宣羊,引用是變量的別名,它使用不同名稱“指向”了內(nèi)存的某一具體地址汰蜘;顯然根據(jù)上面左值右值的說(shuō)明可以發(fā)現(xiàn)仇冯,如果某個(gè)變量沒(méi)有在內(nèi)存內(nèi)(右值),而我們又想對(duì)他定義引用族操,怎么辦赞枕?這就有了右引用的用武之地;

int a = 10;
int &&c = 10; 

正常情況下上面的代碼中坪创,第一行的右值“10”的生存周期只在當(dāng)行有效炕婶。在執(zhí)行第二行時(shí),對(duì)應(yīng)的寄存器或者內(nèi)存會(huì)釋放掉莱预。程序會(huì)申請(qǐng)一個(gè)內(nèi)存地址叫做‘a(chǎn)’柠掂,地址內(nèi)存放10。
對(duì)于第二行依沮,右值“10”在定義c后涯贞,會(huì)轉(zhuǎn)化為左值被c引用,并且在執(zhí)行完當(dāng)前行后危喉,“10”繼續(xù)存在在內(nèi)存中(有地址被c記錄)直到c被釋放宋渔,顯然c解決了右值生存周期的問(wèn)題。

那為什么需要右值引用這種看似很無(wú)聊的操作呢:
減少不必要的拷貝辜限,同時(shí)完成必要的數(shù)據(jù)轉(zhuǎn)換皇拣!

來(lái)個(gè)例子

#include <iostream>  
using namespace std;  

int fun(int &v1,  const int &v2){
    
    v1 = v2 + 1;
    cout << "-------入?yún)⒁?-------" << endl;
    cout << "   v1  =" << v1 <<"    "<<"    &v1 = "<<&v1<< endl;
    cout << "   v2  =" << v2 <<"    "<<"    &v2 = "<<&v2<< endl;
    cout << "-----------------------" << endl;
    return 0;
}

int main()  
{   
    int v1 = 1;
    int v2 = 1;
    cout << "-------入?yún)⒍x--------" << endl;
    cout << "   v1  =" << v1 <<"    "<<"    &v1 = "<<&v1<< endl;  
    cout << "   v2  =" << v2 <<"    "<<"    &v2 = "<<&v2<< endl;  
    cout << "-----------------------" << endl;
    fun(v1, v2);
    
    return 0;  
}  

-------入?yún)⒍x--------
   v1  =1        &v1 = 0x7fff062557dc
   v2  =1        &v2 = 0x7fff062557d8
-----------------------
-------入?yún)⒁?-------
   v1  =2        &v1 = 0x7fff062557dc
   v2  =1        &v2 = 0x7fff062557d8
 -----------------------

const 引用的特殊性

上面例子中const修飾函數(shù)入?yún)ⅲ瞬蛔屝薷暮推胀ㄈ雲(yún)⒁盟坪鯖](méi)什么區(qū)別薄嫡。
如果把變量v2修改為float氧急,我們發(fā)現(xiàn)編譯并不會(huì)報(bào)錯(cuò),修改后的代碼如下:

#include <iostream>  
using namespace std;  
int fun(int &v1,  const int &v2){
   
   v1 = v2 + 1;
   cout << "-------入?yún)⒁?-------" << endl;
   cout << "   v1  =" << v1 <<"    "<<"    &v1 = "<<&v1<< endl;
   cout << "   v2  =" << v2 <<"    "<<"    &v2 = "<<&v2<< endl;
   cout << "-----------------------" << endl;
   return 0;
}

int main()  
{  

   int v1 = 1;
   float v2 = 1;
   cout << "-------入?yún)⒍x--------" << endl;
   cout << "   v1  =" << v1 <<"    "<<"    &v1 = "<<&v1<< endl;  
   cout << "   v2  =" << v2 <<"    "<<"    &v2 = "<<&v2<< endl;  
   cout << "-----------------------" << endl;
   fun(v1, v2);
   fun(v1,2);
   return 0;  
}  

代碼執(zhí)行結(jié)果如下:

-------入?yún)⒍x--------
   v1  =1        &v1 = 0x7fff7782a864
   v2  =1        &v2 = 0x7fff7782a860
-----------------------
-------入?yún)⒁?-------
   v1  =2        &v1 = 0x7fff7782a864
   v2  =1        &v2 = 0x7fff7782a868
-----------------------
-------入?yún)⒁?-------
   v1  =3        &v1 = 0x7fff7782a864
   v2  =2        &v2 = 0x7fff7782a86c
-----------------------

發(fā)現(xiàn)編譯器通過(guò)const int & v2 自動(dòng)幫我們完成了數(shù)據(jù)類型轉(zhuǎn)換毫深。(個(gè)人理解是const關(guān)鍵字說(shuō)明該引用不會(huì)影響函數(shù)外的變量且會(huì)申請(qǐng)新的內(nèi)存地址變?yōu)樽笾捣园樱宰詣?dòng)完成內(nèi)存轉(zhuǎn)換不會(huì)有任何風(fēng)險(xiǎn))。
這里可以嘗試修改v1的類型為float 或者在fun函數(shù)的第一個(gè)入?yún)橛抑稻鶡o(wú)法編譯通過(guò)哑蔫。

當(dāng)然其實(shí)在復(fù)雜的工程代碼上钉寝,有些更加變態(tài)的代碼會(huì)有如下需求:

int fun(const T &a); // 函數(shù)申明
/**/
int b1 = fun(new T);
T t; 
int b2 = fun(t)闸迷;

其中的差別需要積累經(jīng)驗(yàn)慢慢體會(huì)嵌纲。

其他

寫法上const關(guān)鍵字可以放在任何位置;常引用隨便綁稿黍;

int &a = 2;       // 左值引用綁定到右值疹瘦,編譯失敗
int &&a = 2;       // 右值引用綁定到右值,編譯ok
int b = 2;        // 非常量左值
const int &c = b; // 常量左值引用綁定到非常量左值巡球,編譯ok
const int d = 2;  // 常量左值
const int &e = c; // 常量左值引用綁定到常量左值言沐,編譯ok
const int &f =2;  // 常量左值引用綁定到右值邓嘹,編程ok
int const &g =2;  // 和上一句等價(jià),編程ok

右值引用不能直接綁定到左值险胰,如果要綁定可以使用std::move()函數(shù)汹押;

int a;
int &&r1 = a;    // 編譯ok
int &&r2 = std::move(a);  //編譯ok
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市起便,隨后出現(xiàn)的幾起案子棚贾,更是在濱河造成了極大的恐慌,老刑警劉巖榆综,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妙痹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鼻疮,警方通過(guò)查閱死者的電腦和手機(jī)怯伊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)判沟,“玉大人耿芹,你說(shuō)我怎么就攤上這事∨埠澹” “怎么了吧秕?”我有些...
    開(kāi)封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)迹炼。 經(jīng)常有香客問(wèn)我砸彬,道長(zhǎng),這世上最難降的妖魔是什么疗涉? 我笑而不...
    開(kāi)封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任拿霉,我火速辦了婚禮吟秩,結(jié)果婚禮上咱扣,老公的妹妹穿的比我還像新娘。我一直安慰自己涵防,他們只是感情好闹伪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著壮池,像睡著了一般偏瓤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上椰憋,一...
    開(kāi)封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天厅克,我揣著相機(jī)與錄音,去河邊找鬼橙依。 笑死证舟,一個(gè)胖子當(dāng)著我的面吹牛硕旗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播女责,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼漆枚,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了抵知?” 一聲冷哼從身側(cè)響起墙基,我...
    開(kāi)封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎刷喜,沒(méi)想到半個(gè)月后残制,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掖疮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年痘拆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氮墨。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纺蛆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出规揪,到底是詐尸還是另有隱情桥氏,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布猛铅,位于F島的核電站字支,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏奸忽。R本人自食惡果不足惜堕伪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望栗菜。 院中可真熱鬧欠雌,春花似錦、人聲如沸疙筹。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)而咆。三九已至霍比,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暴备,已是汗流浹背悠瞬。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人浅妆。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓玛痊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親狂打。 傳聞我的和親對(duì)象是個(gè)殘疾皇子擂煞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容