C 右值引用的初步理解

2021-07-29 16:04:01 字數 2441 閱讀 8498

在c++11中,新增了右值引用是對於經常使用stl的人來說非常有意義的事情。

初步理解為 move語義對於效能的提公升。

std::string("abc") //「abc為臨時變數,這裡將呼叫move語義 將abc移動到容器中。

std::vector> v;

std::vectorvv;

vv.pushback(1);

...//dosomething

v.pushback(std::move(w));  //幾乎沒有開銷。

printf("%d\n",w.size());  //   print 0

以下引用自其它博文的說法

c++中臨時物件可能會大量存在,比如string/stl呼叫中。臨時物件中的資源(buffer或者字串)會隨著臨時物件的析構而消失,所以一般會在物件析構前把它們(資源)拷貝出來,而不會直接引用這些資源,否則會野指標。

其實,既然已經是臨時物件了,馬上就會被析構掉,所以趕在析構前改一下裡面的內容也不會帶來太多負面影響,當然是在控制良好的前提下。基於這個思路,我們可以放心大膽的直接引用臨時物件中的資源指標(比如指標賦值,引用該資源),然後把它置空(防止被臨時物件釋放掉,囧),或者更屌一點的,把我們意圖釋放的指標,直接賦值給臨時物件的該指標,借助臨時物件在析構時會釋放它的資源的時機,把我們想釋放的東西給釋放掉!

多麼精妙!

在c11之前,臨時物件只能以 const myclass& my_object 這種方式傳遞,有const在,所以臨時物件是不能被修改的。但是c11引入了右值引用 myclass&&,導致我們可以修改臨時變數了!

假如你是函式的提供者,你提供了帶右值引用的引數,那麼,你就大膽的去引用它的資源,修改它的資源吧,不用擔心它還會被使用到,當函式返回之後。因為它是右值引用,該函式的呼叫者會保證這個引數不會再被使用到。

假如你是函式的呼叫者,當你發現你有乙個左值物件my_object即將不再被使用到了,就可以用move語義把它轉成右值引用丟給函式,任函式去修改它的內容無所謂,因為你確定它不再被使用了(如果你確定不了,那就不能使用move語義)。當然,假如你處理的已經是右值了(比如函式返回值),那就跟以前沒什麼兩樣。

2018.02.06

今天在工作中繼續學習模板程式設計相關問題時,又遇到了右值引用和完美**相關問題。

一年後我又回來看我當初的理解,還是那句話 too young too ****** sometimes native!

回頭再看當時的理解基本已經覺得是錯誤的了。現在就回過頭來再議這個c++ 右值引用相關問題。

在我們上面的膚淺理解中,把 std::move 作為了很多東西的第一推動力,這是相當錯誤的。

經過一年的沉澱,其實對於 std::move來說,只做了一件事。可以初步的理解為 (不過當然是錯誤的)

templatet&& move(t& val)

move 只是純粹的將乙個左值轉化為了乙個右值,但當年誤打誤撞的**有效果的原因在於,msvc 14.0的 stl實現基本都已經實現了移動語義,相當於對於 vector::push_back()有兩個版本的實現,簡單寫如下:

templateclass vector

;

而對應的型別 t 也實現了移動拷貝,如下:

class t

t(t&& other)

};

所以,整個**跑起來的確有效能提公升,真是瞎貓碰見死耗子哈哈哈。

再來說一下原來沒有碰觸的完美** std::forward()

// template function forward

templateinline

constexpr _ty&& forward(

typename remove_reference<_ty>::type& _arg) _noexcept

templateinline

constexpr _ty&& forward(

typename remove_reference<_ty>::type&& _arg) _noexcept

當我們將乙個右值引用傳入函式時,他在實參中有了命名,所以繼續往下傳或者呼叫其他函式時,根據c++ 標準的定義,這個引數變成了乙個左值。那麼他永遠不會呼叫接下來函式的右值版本,這可能在一些情況下造成拷貝。為了解決這個問題 c++ 11引入了完美**,根據右值判斷的推倒,呼叫forward 傳出的值,若原來是乙個右值,那麼他轉出來就是乙個右值,否則為乙個左值。

這樣的處理就完美的**了原有引數的左右值屬性,不會造成一些不必要的拷貝。**如下:

#include #include #include using namespace std;

int main()

這才是整個右值引用正確的理解。

當然我希望我一年之後再回來看這篇部落格,又能寫一些新的東西。

現代C 理解右值引用

右值引用是c 11中新增新的引用型別。右值引用只不過是一種新的 c 語法。基於右值引用,引申出的 2 種 c 程式設計技巧 移動語義和完美 難以理解。引入右值引用的主要目的是提高 程式執行效率。有些物件在複製時需要進行深複製 拷貝 深拷貝往往非常耗時。合理使用右值引用可以避免深複製操作。右值引用通過...

c 左值 右值 右值引用 左值引用

c 裡一切值必須屬於左值 右值兩者之一。左值 一切變數 包括用const修飾的變數 物件 包括引用都屬於左值 右值 一切字面值 可以是巨集 臨時無名物件 函式返回值 表示式 如a n 說明一下 函式返回值,返回的是某乙個型別的值,並不是返回變數。左值並不是說能放在 左邊的值就是左值 雖然用const...

c 左值 右值 左值引用 右值引用

在c語言中,左值認為是賦值語句的左側,右值認為是賦值語句的右側。在c 中,意義稍有不同。c 中,每乙個表示式會產生乙個左值或者右值,相應的,該表示式也就被稱作 左值表示式 右值表示式 乙個左值表示式的求值結果是乙個物件或者是乙個函式。左值可以當右值使用,而右值不能當左值使用。c prime 中這麼簡...