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