左值和右值判斷:
1)可位於賦值號(=)左側的表示式就是左值;反之,只能位於賦值號右側的表示式就是右值。
2)有名稱的、可以獲取到儲存位址的表示式即為左值;反之則是右值。
例如:
int
main()
移動建構函式
class
test
;test
(const test & parm)
:data
(new
int(
*parm.data)
)test
(test &&parm)
:data
(parm.data)
test&
operator=(
const test &parm)
~test()
;public
:int
* data =
null;}
;int
main()
getchar()
;return0;
}
提到了移動構造,就要提完美**完美**(perfect forwarding)問題是指函式模板在向其他函式**(傳遞)自身引數(形參)時該如何保留該引數(實參)的左右值屬性的問題。也就是說函式模板在向其他函式**(傳遞)自身形參時,如果相應實參是左值,它就應該被**為左值;同樣如果相應實參是右值,它就應該被**為右值。這樣做是為了保留在其他函式針對**而來的引數的左右值屬性進行不同處理(比如引數為左值時實施拷貝語義;引數為右值時實施移動語義)的可能性。如果將自身引數不分左右值一律**為左值,其他函式就只能將**而來的引數視為左值,從而失去針對該引數的左右值屬性進行不同處理的可能性。
首先提一下引用摺疊
我們把 引用摺疊 拆解為 引用和 摺疊 兩個短語來解釋。
首先,引用的意思眾所周知,當我們使用某個物件的別名的時候就好像直接使用了該物件,這也就是引用的含義。在c++11中,新加入了右值的概念。所以引用的型別就有兩種形式:左值引用t&和右值引用t&&。
其次,解釋一下摺疊的含義。所謂的摺疊,就是多個的意思。上面介紹引用分為左值引用和右值引用兩種,那麼將這兩種型別進行排列組合,就有四種情況:
左值-左值 t& &所有的引用摺疊最終都代表乙個引用,要麼是左值引用,要麼是右值引用。左值-右值 t& &&
右值-左值 t&& &
右值-右值 t&& &&
規則就是:
如果任一引用為左值引用,則結果為左值引用。否則(即兩個都是右值引用),結果為右值引用。如下
函式引數宣告的型別 傳入實參的型別 r的型別
t& tr r&
t& tr& r&
t& tr&& r&
t&& tr r&&
t&& tr& r&
t&& tr&& r&&
測試用例
#include
#include
#include
void
func
(int
& t)
void
func
(const
int& t)
void
func
(const
int&& t)
template
<
typename t>
t&&forward
(t ¶m)
//雖然簡陋,但是std::forward大抵就是做這些事
template
<
typename t>
void
myfun
(t&& t)
intmain()
直接執行
去掉注釋,使用完美**後
關於完美**,認為了解即可
c 左值 右值 右值引用 左值引用
c 裡一切值必須屬於左值 右值兩者之一。左值 一切變數 包括用const修飾的變數 物件 包括引用都屬於左值 右值 一切字面值 可以是巨集 臨時無名物件 函式返回值 表示式 如a n 說明一下 函式返回值,返回的是某乙個型別的值,並不是返回變數。左值並不是說能放在 左邊的值就是左值 雖然用const...
c 左值 右值 左值引用 右值引用
在c語言中,左值認為是賦值語句的左側,右值認為是賦值語句的右側。在c 中,意義稍有不同。c 中,每乙個表示式會產生乙個左值或者右值,相應的,該表示式也就被稱作 左值表示式 右值表示式 乙個左值表示式的求值結果是乙個物件或者是乙個函式。左值可以當右值使用,而右值不能當左值使用。c prime 中這麼簡...
C 左值 右值 左值引用 右值引用
就變數而言,對於一些變數,我們只會讀取並使用它們的值,而不會改變他們的值 唯讀 對於其餘的變數,我們既會讀取它們的值,有的時候還會改變它們的值 讀寫 這是很常見的。在c 中,前一種變數稱為右值,後一種變數稱為左值,例如 int a 1 a是左值,1是右值稍稍不同的一點是,在c 中,乙個變數是左值還是...