文章目錄
- 什么是左值
- 什么是右值
- 純右值:
- 將亡值:
- 左值引用
- 右值引用
在C語言中我們常常會提起左值(lvalue) 和 右值(rvalue) 這樣的稱呼。編譯器在編譯程序報錯時, 有時也會報出錯誤信息中會包含左值、右值的說法。但是左值和右值并沒有一個嚴謹的定義。大多數時候左右值的定義與其判別方法是一體的。
一個典型的的判別方法就是,在賦值表達式中。出現在等號左邊的就是
左值
,而在等號右邊的,則稱為
右值
。
例如:
a = b + c;
在這個賦值表達式中,a就是一個左值,而b+c則是一個右值。這種識別左值、右值的方法在C++中依然有效。
不過C++中還有一個被廣泛認同的說法,那就是 可以取地址的、有名字的就是左值,反之 , 不能取地址的、沒有名字的就是右值。
在這個賦值表達式中,&a是運行的操作。但是&(b+c) 這樣的操作則不會通過編譯。因此 a 是一個左值, (b+c) 是一個右值。
什么是左值
可以和按照C++上的說法:可以取地址的、有名字的就是左值。
什么是右值
不能取地址的、沒有名字的就是右值。具體在C++11中,右值是由兩個概念構成的。
一個是將亡值。一個是純右值。
純右值:
純右值(prvalue, Pure Rvalue)就是C++98標準中的右值概念,比如函數返回的臨時變量值。還有一些運算表達式,比如 1 + 3 產生的臨時變量值。
不跟對象關聯的字面量值,比如:2、‘c’ 、true。lambda表達式 。都是純右值。
將亡值:
將亡值 (xvalue, eXpiring) 是C++11中新增的跟右值引用相關的表達式。這樣的表達式通常是將要被移動的對象(移為他用)。
比如:返回右值引用 T&& 的函數返回值;std::move的返回值; 轉換為T&&的類型轉換函數的返回值。
注
:在C++11的程序中,所有的值必屬于左值、將亡值、純右值三者之一。
左值引用
左值引用就是C++98中的引用 T&。在沒出來C+11的右值引用之前。說的引用都是指的左值引用。
例如:
int a = 10;
int & b = a;
const int & c = a;
b和c都是 左值引用。b是非常量左值引用。c是常量左值引用。
左值引用顧名思義就是對一個左值進行引用的類型。也就是等號右側的是一個左值(可取地址的)。
而常量左值引用類型 比較特殊,也可以對右值進行引用。如 const int &d = 2; 但是 int &d = 2;是編譯不過的。
因此常量左值引用類型也稱為萬能的引用類型。通過常量左值引用不可以修改所引用的內容。而 非常量左值引用可以修改引用的內容。
右值引用
右值引用是C++11中新增的一種引用類型,顧名思義就是對一個右值進行引用的類型。事實上,由于右值不具有名字。我們也只能通過引用的方式找到的它的存在。
例如:T && a = ReturnRvalue();
這個表達式中,假設ReturnRvalue函數返回一個右值,我們就聲明了一個名為a的右值引用,其值等于ReturnRvalue函數返回的臨時變量的值。
注意
: T&& 就是 右值引用的類型。與左值引用比較多了個 &符號。和二級指針的使用方式 不一樣。C++上不存在二級引用。
注意
:引用 也是一個變量,不過是一種特殊的變量,擁有自己的類型。
相同點
:
左值引用和右值引用都是屬于引用類型。
無論聲明的一個左值引用還是右值引用,都必須立即進行初始化。而其原因可以理解為是引用類型本身自己并不擁有所綁定的對象的內
存,只是該對象的一個別名,幾乎不占用什么內存。
不同點
:
左值引用是具名變量值的別名,而右值引用則是不具名(匿名)變量的別名。
右值引用是不能夠綁定到任何的左值的。比如:
int c;
int && d = c;//編譯不過
相對的左值引用也是不可以綁定到右值(由右值進行初始化)的。
比如:
T & e = ReturnRvalue();//編譯不過。
但是存在例外:const T & e = ReturnRvalue();//編譯通過。上面我們說常量左值引用是萬能引用類型,它可以接收非常量左值(如:int
c),常量左值(如:const int c)、右值對其進行初始化。
右值引用類型的使用場景:用于移動構造函數的形參類型 和 移動語義緊密相關聯。