左值 右值與右值引用

2021-09-24 21:06:10 字數 2136 閱讀 2619

在c語言中,我們常常會提起左值(lvalue)、右值(rvalue)這樣的稱呼。而在編譯程式時,編譯器有時也會在錯誤的資訊中包含左值、右值的說法。不過左值、右值通常不是通過乙個嚴謹的定義而為人所知的,大多數時候左右值的定義與判別方法是一體的。乙個典型的判別方法就是,在賦值表示式中,出現在等號左邊的就是「左值」,而在等號右邊的,則成為「右值」。比如:

a = b + c
在這個賦值表示式中,a就是乙個左值,而b+c則是乙個右值。這種識別左值、右值的方法在c++中依然有效。不過c++中還有乙個被廣泛認同的說法,那就是可以取位址的、有名字的就是左值,反之不能取位址的、沒有名字的就是右值。那麼這個加法賦值表示式中,&a是允許的操作,但&(b+c)這樣的操作則不會通過編譯。因此a是乙個左值,(b+c)是乙個右值。

這些判別方法通常都非常有效。更為細緻地,在c++11中,右值是由兩個概念構成的,乙個將亡值(xvalue,expiring value),另乙個則是純右值(prvalue,pure rvalue)。

其實純右值就是c++98標準中右值的概念,講的是用於辨識臨時變數和一些不跟物件關聯的值,比如

非引用返回的函式返回的臨時變數值

一些算數表示式,比如1 + 3產生的臨時變數值

不與物件關聯的字面量值,比如:2、『c』、true

型別轉換函式的返回值

lambda表示式

而將亡值則是c++11新增的跟右值引用相關的表示式,這樣表示式通常是將要被移動的物件(移位他用),比如

返回右值引用t&&的函式返回值

std::move的返回值

轉換為t&&的型別轉換函式的返回值

而剩餘的,可以標識函式、物件的值都屬於左值。在c++11的程式中,所有的值必屬於左值、將亡值、純右值三者之一。

通常情況下,右值引用是不能繫結到任何的左值的。而在c++98標準中就已經出現的左值引用是否可以繫結到右值(由右值進行初始化)?比如:

t &e = returnrvalue();

const t &f = returnrvalue();

這樣的語句是否能夠通過編譯呢?這裡的答案是:e的初始化會導致編譯時錯誤(注:我在vs2017上是可以編譯通過),而f則不會。

出現這樣的狀況的原因是,在常量左值引用在c++98標準中開始就是個「萬能」的引用型別。他可以接受非常量左值、常量左值、右值對其進行初始化。而且在使用右值對其初始化的時候,常量左值引用還可以像右值引用一樣將右值的生命期延長。不過相比於右值引用所引用的右值,常量左值所引用的右值在它的「餘生」中只能是唯讀的。相對地,非常量左值只能接受非常量左值對其進行初始化。

在c++98通過左值引用來繫結乙個右值的情況並不少見,比如:

const bool & judgement = true;

const bool judgement = true;

可能很多程式設計師都沒有注意到其中的差別(從語法上講,前者直接使用了右值並為其「續命」,而後者的右值在表示式結束後就銷毀了)。

事實上,即使在c++98中,我們也常可以使用常量引用來減少臨時物件的開銷,例子如下:

class copyable

; copyable(const copyable&) };

copyable returnrvale()

void acceptval(copyable )

void acceptref(const copyable &)

int main()

acceptval使用了值傳遞引數,而acceptref使用了引用傳遞。在以returnrvalue返回的右值為引數的時候,acceptref就可以直接使用產生的臨時值(並延長其生命期),而acceptval則不能直接使用臨時物件。

結果如下:

pass by value

copied

copied

pass by ref

copied

在c++11中,同樣地如果以右值引用為引數宣告如下函式:

void acceptrvalueref(copyable &&){}
這樣也可以減少臨時變數拷貝的開銷,還可以在acceptrvalueref中修改改臨時值。

參考:《深入理解c++11》

左值 右值 左值引用 右值引用

2015 06 01 15 07 404人閱讀收藏 舉報 c 11 5 一 c 中的左值和右值 誤區 左值位於等號左邊,右值位於等號右邊。c 11中的定義 左值表示式表示的是乙個物件的身份 在記憶體中的位置 而右值表示式表示的是物件的值 內容 左值和右值都是針對表示式而言的,左值是持久的,右值是短暫...

左值 左值引用 右值 右值引用

1 左值和右值的概念 左值是可以放在賦值號左邊可以被賦值的值 左值必須要在記憶體中有實體 右值當在賦值號右邊取出值賦給其他變數的值 右值可以在記憶體也可以在cpu暫存器。乙個物件被用作右值時,使用的是它的內容 值 被當作左值時,使用的是它的位址。2 引用 引用是c 語法做的優化,引用的本質還是靠指標...

左值 左值引用 右值 右值引用

1 左值和右值的概念 左值是可以放在賦值號左邊可以被賦值的值 左值必須要在記憶體中有實體 右值當在賦值號右邊取出值賦給其他變數的值 右值可以在記憶體也可以在cpu暫存器。乙個物件被用作右值時,使用的是它的內容 值 被當作左值時,使用的是它的位址。2 引用 引用是c 語法做的優化,引用的本質還是靠指標...