日韩性视频-久久久蜜桃-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)站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 根深蒂固在线观看 | 日日摸夜夜添夜夜 | 日本精品一区在线 | 国产精品久久久影院 | 成人欧美一区二区三区黑人动态图 | 青娱乐最新视频 | 欧美在线一级视频 | 91久久久久久久久久久久久 | 欧美做爰xxxⅹ性欧美大片 | 一区二区不卡视频在线观看 | 毛片天天看 | 人人射av | 国内毛片毛片毛片毛片毛片 | 天天色天天操天天 | 爱爱视频网站 | 91久久精品国产 | 打开每日更新在线观看 | 国产综合日韩 | caoporn超碰97| 天天摸天天操天天干 | 色图18p| 看全黄大色黄大片美女人 | 国产精品玖玖玖 | 91av在线视频播放 | 日韩视频在线免费播放 | 黑人巨大猛烈捣出白浆 | 亚洲视频在线观看免费视频 | 欧美成人一区二区三区四区 | h在线网站 | 伊人网成人网 | 韩国av在线免费观看 | 都市激情 自拍偷拍 | 日韩精品第一 | 男人的天堂免费视频 | 伊人影院在线观看视频 | 夜夜操天天 | 国产一区二区三区视频在线播放 | 国产小视频一区 | 久久久久二区 | 96免费视频 | 男人天堂中文字幕 | 激情自拍偷拍 | 浪浪视频污 | 欧美熟妇精品黑人巨大一二三区 | 中文字幕无码乱人伦 | 好吊一二三区 | 婷婷色综合 | 九九热精品免费视频 | 91精品国产一区二区无码 | 红桃成人在线 | 看毛片的网址 | 亚洲影视一区 | 亚洲 小说区 图片区 都市 | 亚洲激情视频在线观看 | 亚洲AV成人无码电影在线观看 | 久久精品导航 | 999视频在线| 中文在线免费视频 | 绿帽在线| 国产盗摄视频在线观看 | 美女黄色一级 | 国产在线观看免费av | 亚洲精品在线观看视频 | 婷婷激情图片 | 处破痛哭a√18成年片免费 | 一级黄视频| 国产精品一区二区人人爽 | 国产精品视频免费在线观看 | 欧美不卡高清 | 久久久久久国产视频 | 四虎影院在线免费播放 | 黑丝一区二区三区 | 精品人成| 日韩欧美国产激情 | 一极毛片 | 欧美在线色视频 | 丰满岳乱妇国产精品一区 | 免费的毛片 | 久久久久香蕉视频 | 五月天堂婷婷 | 欧美少妇15p | 丁香花在线影院观看在线播放 | 欧美一区二区免费电影 | 欧美videossex极品 | 久久婷婷成人综合色 | 日本新japanese乱熟 | 91色在线播放 | 伊人国产在线视频 | 成人网站在线进入爽爽爽 | 蜜桃在线一区二区三区 | 在线的av| 亚洲精品一区二区口爆 | 九九九九九精品 | 欧美做爰猛烈床戏大尺度 | 天堂在线一区二区 | 久久久毛片 | 欧美污视频在线观看 | 美女自卫网站 | 日韩在线看片 |