當(dāng)前位置:首頁 > 公眾號精選 > C語言與CPP編程
[導(dǎo)讀]來源:georgeguo C++98 中表達(dá)式值的類型只有左值和右值兩種類型,可以取到地址的表達(dá)式就是左值,不是左值的值就是右值,而C++11中將表達(dá)式的值類型劃分成了lvalue(左值)、rvalue(右值)、prvalue(純右值)、xvalue(將亡值)、gvalue(泛左值) 5種。下

來源:georgeguo


C++98 中表達(dá)式值的類型只有左值和右值兩種類型,可以取到地址的表達(dá)式就是左值,不是左值的值就是右值,而C++11中將表達(dá)式的值類型劃分成了lvalue(左值)、rvalue(右值)、prvalue(純右值)、xvalue(將亡值)、gvalue(泛左值) 5種。下文從基本概念并結(jié)合實際的例子區(qū)分C++11中的表達(dá)式值類型。

基本概念

表達(dá)式


  • 表達(dá)式的定義
    定義: 由運算符(operator)和運算對象(operand)構(gòu)成的計算式(類似于數(shù)學(xué)上的算術(shù)表達(dá)式)。
    舉例: 字面值(literal)和變量(variable)是最簡單的表達(dá)式,函數(shù)的返回值也被認(rèn)為是表達(dá)式。

值類別


  • 表達(dá)式是可求值的,對表達(dá)式求值將得到一個結(jié)果(result)。這個結(jié)果有兩個屬性:類型和值類別(value categories)。

  • 在c++11以后,表達(dá)式按值類別分,必然屬于以下三者之一:左值(left value,lvalue),將亡值(expiring value,xvalue),純右值(pure rvalue,pralue)。其中,左值和將亡值合稱泛左值(generalized lvalue,glvalue),純右值和將亡值合稱右值(right value,rvalue)。


  • C++11中右值rvalue的概念包括兩個部分:

1、將亡值(xvalue. expiring value),xvalue是C++11新增的概念,與右值引用相關(guān)的表達(dá)式,如: 將要被移動的對象、T&&函數(shù)返回值、std::move返回值和轉(zhuǎn)換為 T&&的類型的轉(zhuǎn)換函數(shù)的返回值等;
2、純右值(pvalue, pure right value),如:非引用返回的臨時變量、運算表達(dá)式產(chǎn)生的臨時變量、原始字面量和lambda表達(dá)式等屬于pvalue;

注意:“左值”是表達(dá)式的結(jié)果的一種屬性,但更為普遍地,通常用“左值”來指代左值表達(dá)式。所謂左值表達(dá)式,就是指求值結(jié)果的值類別為左值的表達(dá)式。在后文中,我們依然用左值指代左值表達(dá)式。對于純右值和將亡值,亦然。

左值、純右值和將亡值的描述

左值


  • 描述:能夠用&取地址的表達(dá)式是左值表達(dá)式。

一個區(qū)分左值和右值的便捷方法:看能不能對表達(dá)式取地址,若能,則為左值,若不能則為右值。所有的具名變量都是左值,而右值是不具名的。

舉例:


  • 函數(shù)名和變量名

  • 返回左值引用的函數(shù)調(diào)用

  • 前置自增/自減運算符連接的表達(dá)式++i/--i

  • 由賦值運算符或復(fù)合賦值運算符連接的表達(dá)式(a=b、a+=b、a%=b)

  • 解引用表達(dá)式*p

  • 字符串字面值"abc"


純右值


描述:滿足下列條件之一的:


  • 1)本身就是赤裸裸的、純粹的字面值,如3、false;

  • 2)求值結(jié)果相當(dāng)于字面值或是一個不具名的臨時對象。


舉例:


  • 除字符串字面值以外的字面值

  • 返回非引用類型的函數(shù)調(diào)用

  • 后置自增/自減運算符連接的表達(dá)式i++/i--

  • 算術(shù)表達(dá)式(a+b、a&b、a<

  • 邏輯表達(dá)式(a&&b、a||b、~a)

  • 比較表達(dá)式(a==b、a>=b、a

  • 取地址表達(dá)式(&a)


將亡值


描述: 在C++11之前的右值和C++11中的純右值是等價的。C++11中的將亡值是隨著右值引用的引入而新引入的。換言之,“將亡值”概念的產(chǎn)生,是由右值引用的產(chǎn)生而引起的,將亡值與右值引用息息相關(guān)。所謂的將亡值表達(dá)式,就是下列表達(dá)式:


  • 1)返回右值引用的函數(shù)的調(diào)用表達(dá)式

  • 2)轉(zhuǎn)換為右值引用的轉(zhuǎn)換函數(shù)的調(diào)用表達(dá)

在C++11中,用左值去初始化一個對象或為一個已有對象賦值時,會調(diào)用拷貝構(gòu)造函數(shù)或拷貝賦值運算符來拷貝資源,而當(dāng)用一個右值(包括純右值和將亡值)來初始化或賦值時,會調(diào)用移動構(gòu)造函數(shù)或移動賦值運算符來移動資源,從而避免拷貝,提高效率。當(dāng)該右值完成初始化或賦值的任務(wù)時,它的資源已經(jīng)移動給了被初始化者或被賦值者,同時該右值也將會馬上被銷毀(析構(gòu))。也就是說,當(dāng)一個右值準(zhǔn)備完成初始化或賦值任務(wù)時,它已經(jīng)“將亡”了。這種右值常用來完成移動構(gòu)造或移動賦值的特殊任務(wù),扮演著“將亡”的角色,所以C++11給這類右值起了一個新的名字——將亡值。

  • 舉例:std::move()、tsatic_cast(x)(X是自定義的類,x是類對象,這兩個函數(shù)常用來將左值強(qiáng)制轉(zhuǎn)換成右值,從而使拷貝變成移動,提高效率。

C++11中值的類型總結(jié)

  • gvalue: has identity

  • lvalue:  has identity and can not be moved from

  • rvalue: can be moved from

  • xvalue: has identity and can be moved from

  • prvalue: does not have identity and can be moved from

對比說明

情況1:++i是左值,而i++是右值


  • ++i對i加1后再賦給i,最終的返回值就是i,所以,++i的結(jié)果是具名的,名字就是i;

  • 而對于i++而言,是先對i進(jìn)行一次拷貝,將得到的副本作為返回結(jié)果,然后再對i加1,由于i++的結(jié)果是對i加1前i的一份拷貝,所以它是不具名的。假設(shè)自增前i的值是6,那么,++i得到的結(jié)果是7,這個7有個名字,就是i;而i++得到的結(jié)果是6,這個6是i加1前的一個副本,它沒有名字,i不是它的名字,i的值此時也是7。

  • 可見,++i和i++都達(dá)到了使i加1的目的,但兩個表達(dá)式的結(jié)果不同。


情況2:解引用表達(dá)式*p是左值,取地址表達(dá)式&a是純右值


  • &(p)一定是正確的,因為p得到的是p指向的實體,&(p)得到的就是這一實體的地址,正是p的值。由于&(p)的正確,所以*p是左值。

  • 而對&a而言,得到的是a的地址,相當(dāng)于unsigned int型的字面值,所以是純右值。


情況3:a+b、a&&b、a==b都是純右值


  • a+b得到的是不具名的臨時對象,而a&&b和a==b的結(jié)果非true即false,相當(dāng)于字面值。


情況4:字符串字面值是左值,而非字符串的字面量是純右值


  • 不是所有的字面值都是純右值,字符串字面值是唯一例外。

  • 早期C++將字符串字面值實現(xiàn)為char型數(shù)組,實實在在地為每個字符都分配了空間并且允許程序員對其進(jìn)行操作,所以類似


cout<<&("abc")<<endl; char *p_char="abc";//注意不是char *p_char=&("abc");


情況5:具名的右值引用是左值,不具名的右值引用是右值。


  • 如:


void foo(int&& t) { // t 被一個右值表達(dá)式初始化 // 但是,t 本身是一個左值 }

繼續(xù)深入學(xué)習(xí)

C++11中的右值引用和移動語義https://www.jianshu.com/p/61ea80fcf943

參考

  • Value categorieshttps://en.cppreference.com/w/cpp/language/value_category

  • 話說C++中的左值、純右值、將亡值http://www.cnblogs.com/zpcdbky/p/5275959.html

  • What are rvalues, lvalues, xvalues, glvalues, and prvalues?https://stackoverflow.com/questions/3601602/what-are-rvalues-lvalues-xvalues-glvalues-and-prvalues

  • Value categorieshttps://en.cppreference.com/w/cpp/language/value_category


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險,如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點: 有效應(yīng)對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學(xué)會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團(tuán))股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉