概念
在C++11中,區別表達式是左值或右值可以做這樣的總結:當一個對象被用作右值的時候,用的是對象的值(內容);當對象被用作左值的時候,用的是對象的身份(在內存中的位置)。左值有持久的狀態,而右值要么是字面常量,要么是在表達式求值過程中創建的對象,即左值持久,右值短暫
以上的定義來自於C++Primer(5th)第121頁和第471頁。可能令人困惑,看了接下來的例子就明白了
特性中的應用
decltype關鍵字
使用關鍵字decltype的時候,左值和右值有所不同。如果表達式的求值結果是左值,decltype作用於該表達式(不是變量)得到一個引用類型,例如,假定p的類型是int*,因為解引用運算符生成左值,所以decltype(*p)的結果是int&。另一方面,因為取地址運算符生成右值,所以decltype(&p)的結果是int**,也就是說,結果是一個指向整型指針的指針。
lambda表達式
lambda表達式是形如auto f = [ ]{ }的函數。
lambda可指定其捕獲列表的類型,[&]表示捕獲列表采用隱式引用捕獲方式lambda函數體中所使用的來自所在函數的實體都采用引用方式使用,[=]表示采用值捕獲方式。
拷貝控制
移動構造函數使用右值引用的形參
引用折疊和實參推斷
引用折疊:在所有情況下(除了一個例外),引用會折疊成一個普通的左值引用類型。
注:引用折疊只能應用於間接創建的引用的引用,如類型別名或模板參數。
這兩個規則導致了兩個重要結果:
如果一個函數參數是一個指向模板類型參數的右值引用(如T&&),則他可以被綁定到一個左值。且
如果實參是一個左值,則推斷出的模板實參類型將是一個左值引用,且函數參數將被實例化為一個普通的左值引用參數(T&)
也暗示了:我們可以將任意類型的實參傳遞給T&&類型的函數參數。
函數重載
我們知道,非常量可以初始化一個底層const,反過來卻不行,所以第一種版本可以接收任何能轉換成類型X的任何對象。第二種版本只可以傳遞非const右值,由於精確匹配規則,傳遞非const右值時,會調用第二種版本,盡管第一種版本也可以接受。
一般來說,我們不需要為函數操作定義接受一個const X&&或是一個普通的X&參數的版本。當我們希望從實參“竊取‘數據時,通常傳遞一個右值引用。為了達到這一目的,實參不能使const的。類似的,從一個對象進行拷貝的操作,不應該改變該對象,因此,通常不需要定義一個接受一個普通的X&參數的版本。