C++11特性——右值引用
??前言:C++11是繼98/03版本之后的大改版,其中增加了許多新特性,得到廣泛的應用。這篇文章就介紹其中的右值引用。希望能夠解釋明白以下三個問題:
??1.什么是右值引用?
??2.右值引用有什么好處?
??3.右值引用的使用說明
1.什么是右值引用
??首先介紹下左右值(我發現自己學了好長時間都沒有對兩者進行區分~)
??對于左值、右值可以簡單的以放在等號左右為區分,等號左邊的是左值,等號右邊的是右值。
??再來詳細的介紹下各自的特點:
????左值:
????1)左值可以取地址
????2)左值可以修改
????3)左值可以放在等號左右兩邊
????右值:
????1)右值不可以取地址
????2)右值不可以直接修改
????3)右值只能放在等號右邊
????4)右值往往是沒有名稱的
??再來舉幾個實例:
??左值舉例:int a; int a = 3;
??上面的a都是左值
??關于右值,C++11將右值分了兩類:純右值、將亡值。從例子上看:
??1)純右值 int a = 3; 就是指等號右邊的常數,上式中的3
??2)將亡值其實就是中間變量的過渡,過渡之后就消亡,可以細分兩種
???(1)函數的臨時返回值 int a = f(3); f(3)的返回值是右值,副本拷貝給a,然后消失
???(2)表達式 像(x+y),其中(x+y)是右值
??在左右值使用時有三個原則,不能違反原則,否則編譯無法通過:
??原則1:右值可以賦給左值,左值不能給右值(左值權限更大)
??原則2:右值無法修改
int a = 10; // 10是右值常數,無法修改??原則3:編譯器允許為左值建立引用,不可以為右值建立引用
int num = 10; int &b = num; √ // num是左值,可以左值建立引用 int &b = 10; × // 10是右值,不可以右值建立引用??有一個問題存在:只有左值可以修改,那如果想對右值進行修改怎么辦? 解決辦法就是——右值引用
??右值引用的語法:&&
??使用右值引用需要注意三個問題:
??1)右值引用必須要進行初始化
??2)不能使用左值進行初始化
int num = 10; int && a = num; × //不能使用左值進行右值初始化 int && a = 10; √??3)右值引用可以對右值進行修改
int &&a = 10; // 這里的a是右值引用,其實是10 a = 100;??可以發現當對右值加上應用后可以修改值也可以修改地址,從功能上升為左值。所以有一種說法:右值引用的本質就是不用拷貝的左值。
2.右值引用的好處?
??先想想引用的目的,傳遞參數有兩種方式:值傳遞和引用傳遞。二者相比引用傳遞的優勢就是通過傳遞地址,來減少一次拷貝。在常規寫程序的時候,使用的都是左值引用。左值引用有兩個使用場景:函數傳參、函數返回值。
??1)函數傳參:int f(int &a);
??2)函數返回值:int& f();
??以上兩種情況使用的都是引用傳遞相比于值傳遞減少了拷貝次數。但有一種情況會出問題:就是返回值是一個臨時對象。如下代碼:
??當返回對象a的地址時,其實a作為在棧上的臨時對象,作用域已經到了,被析構。這樣如果外界再對這個地址進行訪問時,就會出現問題。這也左值引用的一個弊端,而右值引用的出現就是為了解決這個問題。那右值引用是怎么解決返回的臨時變量析構? 當返回值為右值引用時,會把返回的臨時變量中的內存居為己用,仍保持了有效性,也避免了拷貝。
3.右值引用的應用
??右值引用的應用場景場景主要有兩個:移動語義、完美轉發。下面分別介紹一下:
??移動語義
??如果我們把賦值這類操作看作資源轉移,那么傳統的資源轉讓是通過拷貝實現的,需要兩份空間。而移動語義是通過移動來實現資源轉讓,只使用一個空間。來看一下移動語義的實現原理:
??首先明確移動語義和右值引用的關系:實現移動語義,就必須使用右值引用。移動語義具體實現是基于移動構造和移動賦值,而移動構造函數和移動賦值函數都需要形參為右值引用類型。
??移動構造和移動賦值負責在不發生拷貝的情況下將資源轉移到目標對象名下,
??ps:這里的構造和賦值一般指對象初始化的兩種方式:
??移動語義避免了拷貝的風險,拷貝有兩方面,一方面避免了淺拷貝可能引發的懸空指針的問題,另一方面也避免了深拷貝昂貴的開銷
??前面說移動語義只能用右值引用實現,那有的時候就是希望用左值怎么辦呢?這里有一個move函數,作用是把左值強制轉換成右值引用,然后就能繼續使用右值引用的特性。一般move用于對象,因為只有對象才會有各種構造函數,對于基本類型就無效啦。
??完美轉發
??存在這樣一種情況:
??這個轉發過程中,i最開始是右值引用,但再次傳遞時卻變成了左值。失去了右值引用的特性,不是我們的預期。這種情況適合使用完美轉發。
??完美轉發指函數模板可以將自己的參數完美地轉發給內部調用的其他函數。完美指不僅能準確轉發參數的值,還能保證轉發參數的左右值屬性不變。簡單點說也就是如果參數是左值引用,轉發給下一個函數還是左值引用;如果參數是右值引用,則轉發給下一個函數還是右值引用。
??完美轉發的實現基于,std::forward,像下面這樣:
??右值引用提供了很好的特性,這篇文章只是簡單的對右值引用一些常見的概念做了解釋,但想要具體使用還遠遠不夠,只有在項目中多多使用,才能融會貫通,加油哇~
總結
以上是生活随笔為你收集整理的C++11特性——右值引用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1.安装msys64_2、vs2017编
- 下一篇: 粒子群算法求解物流配送路线问题(pyth