僅為個人理解,個人筆記
部分**和內容引用於文章從4行**看右值引用
**(來自鏈結文章裡)
#include using namespace std;
int g_constructcount=0;
int g_copyconstructcount=0;
int g_destructcount=0;
struct a
加上-fno-elide-constructors 輸出結果
construct: 1
copy construct: 1
destruct: 1
destruct: 2
解釋
因為在main函式裡採用了右值引用,此時a變數不再是乙個物件,而是乙個引用(引用本質上是乙個指標常量),且a存放的位址是臨時物件的位址,且臨時物件不會出棧,因此臨時物件也不會析構,在main函式結束時才會統一出棧,因此a變數和臨時變數的生命週期一樣,是main()函式棧的生命週期
採用右值引用後相對沒有採用右值引用,提高了時間效率(取消了臨時物件的拷貝和析構),但在mian()函式棧裡要多消耗一小點空間,這個空間根據系統不同而不同,例如32位系統就會在main()函式棧裡多消耗32bit
移動建構函式舉例
classname(classname&& rightvlue)
只有在賦值語句(如=號)右邊的值是右值時才會使用這個移動建構函式,例如函式的返回值,或者應用移動語義std::move將左值物件轉換成乙個右值物件
作用:因為拷貝建構函式一定要進行深拷貝(避免類內的指標漂移),因此在對臨時物件進行拷貝時也要進行深拷貝,這樣增加了不必要的開銷,因為呼叫拷貝建構函式進行深拷貝是為了保護被拷貝的物件,但是臨時物件在拷貝構造函式呼叫完後,就直接析構了(如果不使用右值引用的話),所以直接寫乙個移動建構函式,當要拷貝的物件是臨時物件(右值)的時候,直接移動物件而不是去拷貝物件(例如臨時物件成員p指向一塊堆記憶體,那麼移動建構函式不是再像拷貝構函式那樣malloc一塊堆記憶體被拷貝,而是直接繼承臨時物件的這一塊堆記憶體,然後將臨時物件的p置空,這樣在析構時也會不刪除這塊堆記憶體),這樣就減小了不必要的開銷
作用:將乙個物件轉換成右值(不管物件原來是左值還是右值)
直接上**
templatevoid print(t&& t)
templatevoid print(t& t)
int main()
輸出:
rvalue
rvalue
作用 : 用在模板函式中,可以按照引數原來的型別進行**
不使用完美**
templatevoid print(t&& t)
templatevoid print(t& t)
template void foo(t&& x)
int main()
輸出 :
lvalue
lvalue
使用完美**
templatevoid print(t&& t)
templatevoid print(t& t)
template void foo(t&& x)
int main()
輸出
rvalue
lvalue
學習筆記 C 右值引用
void f string s 之前不知道兩個 是什麼意思,還以為是引用的引用,類似於二級指標的東西。後來參考了這篇文章 class a public a cout constructor 明白了這個是右值引用。首先需要明確一下左值和右值的定義 右值通過排他性定義,不是左值就是右值。a 就是乙個右值...
c 左值 右值 右值引用 左值引用
c 裡一切值必須屬於左值 右值兩者之一。左值 一切變數 包括用const修飾的變數 物件 包括引用都屬於左值 右值 一切字面值 可以是巨集 臨時無名物件 函式返回值 表示式 如a n 說明一下 函式返回值,返回的是某乙個型別的值,並不是返回變數。左值並不是說能放在 左邊的值就是左值 雖然用const...
c 左值 右值 左值引用 右值引用
在c語言中,左值認為是賦值語句的左側,右值認為是賦值語句的右側。在c 中,意義稍有不同。c 中,每乙個表示式會產生乙個左值或者右值,相應的,該表示式也就被稱作 左值表示式 右值表示式 乙個左值表示式的求值結果是乙個物件或者是乙個函式。左值可以當右值使用,而右值不能當左值使用。c prime 中這麼簡...