C++筆記:左值和右值

這兩個概念看似簡單,其實大部分人很多時候都沒有細分他們的差別。最近看到primer書裏討論rvalue reference(右值的引用)時覺得自己應該再回去看看。而事實上左值和右值本身也確實很簡單。

這是微軟在VS2017中對左右值的定義:https://msdn.microsoft.com/en-us/library/f90831hc.aspx
Every C++ expression is either an lvalue or an rvalue. An lvalue refers to an object that persists beyond a single expression. You can think of an lvalue as an object that has a name. All variables, including nonmodifiable (const) variables, are lvalues. An rvalue is a temporary value that does not persist beyond the expression that uses it. To better understand the difference between lvalues and rvalues, consider the following example:

在《C++ Primer》第五版中,對左右值的說明如下:

Generally speaking, an lvalue expression refers to an object’s identity whereas an rvalue expression refers to an object’s value.

其實早先lvalue就是如字面指“可以用在賦值符號左邊的值”,直到ISO C加入了“const”關鍵字。所以人們發現並不是所有左值都可以被賦值,所以定義了modifiable lvalues。在C99中對modifiable lvalues的定義爲:

an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.

左值可以隨時轉化爲右值,然而右值一般不可以轉變爲左值,除了一些特殊情況,例如:解引用*操作符

int arr[] = {1, 2};
int* p = &arr[0];
*(p + 1) = 10;   // OK: p + 1 is an rvalue, but *(p + 1) is an lvalue

在c++標準中對lvalue-to-rvalue conversions的描述爲:

An lvalue (3.10) of a non-function, non-array type T can be converted to an rvalue. […] If T is a non-class type, the type of the rvalue is the cv-unqualified version of T. Otherwise, the type of the rvalue is T.

CV-qualifier is a term used to describe const and volatile type qualifiers.

Rvalue References(C++11)

rvalue references(右值引用)用&&表示。它與左值引用&不同,不能互相引用。

int i=42;
int &r=i;               //ok:r refers to i
int &&rr=i;             //error:cannot bind an rvalue reference to an lvalue
int &r2=i*42;           //error:i*42 is an rvalue
const int &r3=i*42;     //ok:we can bind a reference to const to an rvalue
int &&rr2=i*42;          //ok:bind rr2 to the result of the multiplication

對於產生右值的表達式,we can bind either an lvalue reference to const or an rvalue reference to such expressions(怕翻譯過來引起誤會就引用primer上的原文)。
可以將右值引用繼續賦值給一個左值引用而非右值引用,因爲這時右值引用本身已經是一個變量,即左值

int &&r=5;
int &&r1=r;     //error
int &r2=r;      //ok
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章