日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

右值引用与移动语义

發(fā)布時間:2024/3/26 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 右值引用与移动语义 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄

一、左、右值引用

1.1 什么是左值

1.2 什么是右值

1.3 右值引用特性

1.4 move語義

二、左、右值引用的比較

三、右值引用的使用場景

3.1 左值引用的短板

3.2 解決方案?

四、移動構造與移動賦值

注意情況

五、萬能引用與完美轉發(fā)

5.1 萬能引用

5.2 完美轉發(fā)


一、左、右值引用

傳統(tǒng)的C++語法中就有引用的語法,而C++11中新增了的右值引用語法特性,所以我們稱之前學習的引用為左值引用。但無論左值引用還是右值引用,其實都是給對象取別名。

1.1 什么是左值

左值是一個表示數(shù)據(jù)的表達式(如變量名或解引用的指針),我們可以獲取它的地址,也可以對它賦
值。左值可以出現(xiàn)賦值符號的左邊,但右值不能出現(xiàn)在賦值符號左邊。定義時const修飾符后的左
值,不能給他賦值,但是可以取它的地址。左值引用就是給左值的引用,給左值取別名。(可以大致理解為,能夠取地址的一般都為左值)

int main() {//以下的p、b、c、*p都是左值int* p = new int(0);int b = 1;const int c = 2;//以下是對上面左值的左值引用int*& rp = p;int& rb = b;const int& rc = c;int& pvalue = *p;return 0; }

1.2 什么是右值

右值也是一個表示數(shù)據(jù)的表達式,如:字面常量、表達式返回值,函數(shù)返回值(非左值引用返回)等等。右值可以出現(xiàn)在賦值符號的右邊,但是不能出現(xiàn)出現(xiàn)在賦值符號的左邊,右值不能取地址。右值引用就是對右值的引用,給右值取別名。

內置類型的右值引用被稱為純右值,自定義類型的右值引用被稱為將亡值

int main() {double x = 1.1, y = 2.2;//以下是常見的右值10;x + y;fmin(x, y);//以下是對右值的右值引用int&& rr1 = 10;double&& rr2 = x + y;double&& rr3 = fmin(x, y);return 0; }

1.3 右值引用特性

右值是不能取地址的,但給右值取別名后,會導致右值被存儲到特定位置,且可以取到該位置的地址。(即可以給右值引用取地址)
因為右值引用是左值

int main() {//不能取字面量10的地址。//但是rr引用后,可以對rr取地址,也可以修改rr。int&& rr = 10;rr = 20;return 0; }

1.4 move語義

按照語法,右值引用只能引用右值,但右值引用一定不能引用左值嗎?

有些場景下,可能真的需要用右值引用去引用左值實現(xiàn)移動語義。當需要用右值引用去引用一個左值時,可以通過move函數(shù)將左值轉化為右值。C++11中,std::move()函數(shù)位于<utility>頭文件中,該函數(shù)名字具有迷惑性,它并不搬移任何東西,唯一的功能就是將一個左值強制轉化為右值,然后實現(xiàn)移動語義。

template<class _Ty> inline typename remove_reference<_Ty>::type&& move(_Ty&& _Arg) _NOEXCEPT {// forward _Arg as movablereturn ((typename remove_reference<_Ty>::type&&)_Arg); } int main() {bjy::string s1("hello world");bjy::string s2(s1);//這里s1是左值,調用的是拷貝構造bjy::string s3(std::move(s1));//將s1 move處理以后,會被當成右值,調用移動構造//一般是不這樣用的,因為我們會發(fā)現(xiàn)s1的資源被轉移給了s3,s1被置空了。return 0; }

二、左、右值引用的比較

左值引用:

1. 左值引用只能引用左值,不能引用右值

2. const左值引用既可以引用左值,也可以引用右值

int main() {//左值引用只能引用左值,不能引用右值。int a = 10;int& ra1 = a;//ra為a的別名//int& ra2 = 10;//編譯失敗,因為10是右值// const左值引用既可引用左值,也可引用右值。const int& ra3 = 10;const int& ra4 = a;return 0; }

右值引用:

1.?右值引用只能引用右值,不能引用左值

2.?右值引用可以move以后的左值

int main() {// 右值引用只能右值,不能引用左值。int&& r1 = 10;int a = 10;int&& r2 = a;// error C2440: “初始化”: 無法從“int”轉換為“int &&”// message : 無法將左值綁定到右值引用// 右值引用可以引用move以后的左值int&& r3 = std::move(a);return 0; }

三、右值引用的使用場景

const左值引用既可以引用左值,也可以引用右值,那么為什么還需要右值引用呢?

?左值引用看似功能已經(jīng)很完善了,但是在面對下面這些情況時,卻捉襟見肘。

3.1 左值引用的短板

當函數(shù)返回對象是一個局部變量,出了函數(shù)作用域就不存在了,就不能使用左值引用返回,只能傳值返回。

3.2 解決方案?

這個時候右值引用便可以解決這個問題了。

// 拷貝構造 string(const string& s) :_str(nullptr), _size(0), _capacity(0) {cout << "string(const string& s) -- 拷貝構造(深拷貝)" << endl;string tmp(s._str);swap(tmp); } // 移動構造 string(string&& s) :_str(nullptr), _size(0), _capacity(0) {cout << "string(string&& s) -- 資源轉移" << endl;swap(s); }

利用右值引用提供了移動構造函數(shù)后,to_string函數(shù)中的str對象會被編譯器識別為將亡值。之后需要發(fā)生構造時,則會自動調用移動構造函數(shù)。移動構造本質是將參數(shù)右值的資源竊取過來,占位已有,那么就不用做深拷貝了,所以它叫做移動構造。就是竊取別人的資源來構造自己,移動構造中沒有新開空間,拷貝數(shù)據(jù),所以比拷貝構造更加高效。

與移動構造類似的還有移動賦值,也是通過右值引用來提高效率。

// 拷貝賦值 string& operator=(const string& s) {cout << "string& operator=(string s) -- 拷貝賦值(深拷貝)" << endl;string tmp(s);swap(tmp);return *this; } // 移動賦值 string& operator=(string&& s) {cout << "string& operator=(string s) -- 移動賦值(資源移動)" << endl;swap(s);return *this; }

?

四、移動構造與移動賦值

那么移動構造和移動賦值有什么需要注意的地方嗎?

在C++98時,我們學習過C++的類中一共有6個默認成員函數(shù)(分別是構造函數(shù)、析構函數(shù)、拷貝構造函數(shù)、拷貝賦值重載、取地址重載、const取地址重載)。但隨著C++11的更新又新增了兩個默認成員函數(shù),即移動構造函數(shù)和移動賦值重載

注意情況

1. 若沒有自主實現(xiàn)移動構造函數(shù),且沒有實現(xiàn)析構函數(shù) 、拷貝構造、拷貝賦值重載中的任意一個。那么編譯器會自動生成一個默認移動構造。默認生成的移動構造函數(shù),對于內置類型成員會執(zhí)行逐成員按字節(jié)拷貝,自定義類型成員則需要看這個成員是否存在移動構造,若存在就調用移動構造,不存在就調用拷貝構造。

2. 若沒有自主實現(xiàn)移動賦值重載函數(shù),且沒有實現(xiàn)析構函數(shù) 、拷貝構造、拷貝賦值重載中的任意一個,那么編譯器會自動生成一個默認移動賦值。默認生成的移動構造函數(shù),對于內置類型成員會執(zhí)行逐成員按字節(jié)拷貝,自定義類型成員則需要看這個成員是否存在移動賦值,若存在就調用移動賦值,不存在就調用拷貝賦值。

3. 若提供了移動構造或者移動賦值中任意一個,編譯器不會自動提供拷貝構造和拷貝賦值。

五、萬能引用與完美轉發(fā)

5.1 萬能引用

模板中的&&不代表右值引用,而是萬能引用,其既能接收左值又能接收右值
模板的萬能引用只是提供了能夠同時接收左值引用和右值引用的能力,但是引用類型就會被限制,在后續(xù)使用中都退化成了左值。所以萬能引用也被稱為引用折疊(即左值引用和右值引用都被折疊為左值)。
也可以換一種理解方式。在前面提到過右值引用的特性,右值引用是左值,且左值引用也是左值。所以不出意外,既能接收左值也能接收右值的萬能引用也是左值。

#include <iostream> using namespace std;void Fun(int& x) { cout << "左值引用" << endl; } void Fun(const int& x) { cout << "const 左值引用" << endl; } void Fun(int&& x) { cout << "右值引用" << endl; } void Fun(const int&& x) { cout << "const 右值引用" << endl; } template<typename T> void PerfectForward(T&& t) {Fun(t); } int main() {PerfectForward(10); //左值引用int a;PerfectForward(a); //左值引用PerfectForward(std::move(a)); //左值引用const int b = 8;PerfectForward(b); //const 左值引用PerfectForward(std::move(b)); //const 左值引用return 0; }

如果希望能夠在傳遞過程中保持它的左值或者右值的屬性, 就需要用到完美轉發(fā)

5.2 完美轉發(fā)

std::forward 完美轉發(fā)在傳參的過程中保留對象原生類型屬性

#include <iostream> using namespace std;void Fun(int& x) { cout << "左值引用" << endl; } void Fun(const int& x) { cout << "const 左值引用" << endl; } void Fun(int&& x) { cout << "右值引用" << endl; } void Fun(const int&& x) { cout << "const 右值引用" << endl; } template<typename T> void PerfectForward(T&& t) {Fun(std::forward<T>(t)); } int main() {PerfectForward(10); //右值引用int a;PerfectForward(a); //左值引用PerfectForward(std::move(a)); //右值引用const int b = 8;PerfectForward(b); //const 左值引用PerfectForward(std::move(b)); //const 右值引用return 0; }

使用場景

在實際開發(fā)中,某些接口函數(shù)是提供了右值引用版本的,譬如STL中vector、list等容器的插入接口。傳入右值參數(shù)并被右值引用接收后,會被認為是左值,無法順利調用到移動構造和移動賦值等函數(shù)(沒有真正減少拷貝、提高效率),這時就需要使用完美轉發(fā)來在傳參過程中保證右值對象的屬性。

總結

以上是生活随笔為你收集整理的右值引用与移动语义的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品久久久久久吹潮 | 亚洲精品久久夜色撩人男男小说 | 在线观看 中文字幕 | 国产一级一区 | 影音先锋在线看 | 6996电视影片免费看 | 我会温柔一点的日剧 | 99人人爽 | 777米奇影视第四色 五月丁香久久婷婷 | 极品蜜桃臀肥臀-x88av | 精品一区国产 | 美女扒开内裤让男人捅 | 欧美sm视频 | 亚洲性激情 | 日本艳妇 | 成年人视频在线看 | 国产精品一区不卡 | 国产精品无码内射 | 中文字幕少妇在线三级hd | 亚洲va久久久噜噜噜无码久久 | 草久久久久 | 我们的生活第五季在线观看免费 | 午夜国产福利在线 | 99在线观看视频 | 日韩免费观看一区二区三区 | 日韩国产欧美在线观看 | 人与拘一级a毛片 | 亚洲精品自拍偷拍 | 牛夜精品久久久久久久99黑人 | 97在线超碰 | 91麻豆国产在线 | 日韩精品视频播放 | 亚洲在线一区二区 | 精品久久蜜桃 | 欧美黄色大全 | 欧美色老头old∨ideo | 亚洲免费观看视频 | 日本捏奶吃奶的视频 | 小柔的裸露日记h | 天天摸天天做天天爽 | 粗大黑人巨茎大战欧美成人 | 熟女人妻在线视频 | 就要日就要操 | 欧美 日韩 国产 在线观看 | 视频国产精品 | www.久操| av三级网| 欧美日韩一区二区区 | 青青草久| 少妇xxxx | 亚洲无码精品国产 | 另类专区成人 | 夜夜草网站 | 观看av | 人人做 | 日韩一区二区三区电影 | 男生女生搞黄色 | 日韩精品一二三四区 | 视频二区在线 | 精品动漫一区二区三区的观看方式 | sao虎视频在线精品永久 | 乳罩脱了喂男人吃奶视频 | 欧美无马 | 六月婷婷网 | 韩国三级在线播放 | 欧洲美女与动交ccoo | 欧美激情久久久久 | 午夜视频久久 | 熟女少妇a性色生活片毛片 亚洲伊人成人网 | 成人片在线免费看 | 国产精品嫩草影院精东 | 精品交短篇合集 | 成人免费观看网站 | 国产精品免费一区二区三区在线观看 | 999精品 | 国产中文字幕在线视频 | 国产精品美女久久久久久久久 | 亚州av网 | 国产精品女人久久久 | 九月婷婷 | 欧美精品1区2区 | 欧美区国产区 | 亚洲资源在线观看 | 中文字幕在线永久 | 内射后入在线观看一区 | 日本人做爰全过程 | 图书馆的女友动漫在线观看 | 一级黄色在线观看 | 久色亚洲| 刘亦菲久久免费一区二区 | 一区二区中文字幕在线观看 | 一级片视频免费看 | 国产三级精品视频 | 五月婷婷激情小说 | 九九操 | 懂色av成人一区二区三区 | 青青操在线观看视频 | 老女人综合网 | 性一交一乱一色一视频麻豆 |