C++11特性-右值引用

什麼是左值,什麼是右值c++

常見的誤區有 = 左邊的是左值,右邊的是右值。函數

左值:具備存儲性質的對象,即lvalue對象,是指要實際佔用內存空間、有內存地址的那些實體對象,例如:變量(variables)、函數、函數指針等。性能

右值:相比較於lvalue就是所謂的沒有存儲性質的對象, 也就是臨時對象。spa

在c++中,臨時對象不能做爲左值,但能夠做爲常量引用const & 設計

 ++i = 3;  // ok
  i++ = 3;  // error C2106: 「=」: 左操做數必須爲左值

++i:i先自增1,++i以後仍是指向i的對象 
i++:先把i自增以後的值丟給一個臨時變量,i++以後指向的是那個臨時變量。若是放在單條語句中,這兩個沒啥區別。指針

int i = 0;  // 在這條語句中,i 是左值,0 是臨時值,就是右值。
在C++11以前,右值是不能被引用的,如:
int &a = 1;   // error C2440: 「初始化」: 沒法從「int」轉換爲「int &」

const int &a = 1;//咱們最多隻能用常量引用來綁定一個右值,如:
int &&a = 1;//在C++11中,咱們能夠引用右值,使用&&來實現:

常量引用能夠綁定一個右值,但缺點是這個值不能改變。code

右值引用&&對象

c++中臨時對象可能會大量存在,好比string/STL調用中。臨時對象中的資源(buffer或者字符串)會隨着臨時對象的析構而消失,因此通常會在對象析構前把它們(資源)拷貝出來,而不會直接引用這些資源,不然會野指針。blog

其實,既然已是臨時對象了,立刻就會被析構掉,因此趕在析構前改一下里面的內容也不會帶來太多負面影響,固然是在控制良好的前提下。基於這個思路,咱們能夠放心大膽的直接引用臨時對象中的資源指針(好比指針賦值,引用該資源),而後把它置空(防止被臨時對象釋放掉),或者更屌一點的,把咱們意圖釋放的指針,直接賦值給臨時對象的該指針,藉助臨時對象在析構時會釋放它的資源的時機,把咱們想釋放的東西給釋放掉!內存

多麼精妙!

在c11以前,臨時對象只能以 const MyClass& my_object 這種方式傳遞,有const在,因此臨時對象是不能被修改的。可是c11引入了右值引用 MyClass&&,致使咱們能夠修改臨時變量了!

假如你是函數的提供者,你提供了帶右值引用的參數,那麼,你就大膽的去引用它的資源,修改它的資源吧,不用擔憂它還會被使用到,當函數返回以後。由於它是右值引用,該函數的調用者會保證這個參數不會再被使用到。

假如你是函數的調用者,當你發現你有一個左值對象my_object即將再也不被使用到了,就能夠用move語義把它轉成右值引用丟給函數,任函數去修改它的內容無所謂,由於你肯定它再也不被使用了(若是你肯定不了,那就不能使用move語義)。固然,假如你處理的已是右值了(好比函數返回值),那就跟之前沒什麼兩樣。

 

右值引用的意義何在

  • 右值引用是用來支持轉移語義的。
  • 轉移語義能夠將資源 (堆,系統對象等)從一個對象轉移到另外一個對象,這樣可以減小沒必要要的臨時對象的建立、拷貝以及銷燬,可以大幅度提升 C++ 應用程序的性能。
  • 臨時對象的維護 ( 建立和銷燬 ) 對性能有嚴重影響。
  • 轉移語義是和拷貝語義相對的,能夠類比文件的剪切與拷貝

有了右值引用和轉移語義,咱們在設計和實現類時,對於須要動態申請大量資源的類,應該設計轉移構造函數和轉移賦值函數,以提升應用程序的效率。 

(1)參數(右值)的符號必須是右值引用符號,即「&&」。

(2)參數(右值)不能夠是常量,由於咱們須要修改右值。

(3)參數(右值)的資源連接和標記必須修改。不然,右值的析構函數就會釋放資源。轉移到新對象的資源也就無效了。

先記錄這麼多,等之後有機會再深刻總結。

相關文章
相關標籤/搜索