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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C/C++编程:右值引用

發布時間:2024/3/26 c/c++ 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C/C++编程:右值引用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

右值引用不過是C++的一種新語法,重要的是基于右值引用引申處理的兩種C++編程技巧:移動語義和完美轉發

右值引用

C++98/03標準中就有引用,用&表示。但是此種引用方式有一個缺陷,即正常情況下只能操作C++中的左值,無法對右值添加引用。舉個例子:

int num = 10; int &b = num; //正確 int &c = 10; //錯誤

如上所示,編輯器允許我們為num左值建立一個引用,但是不可以為10這個右值建立引用。因此,C++93/03標準中的引用又叫做“左值引用

注意,雖然C++98/03標準不支持右值建立非常量左值引用,但是允許常量左值引用操作右值。也就是說,常量左值引用既可以操作左值,也可以操作右值。例如:

int num = 10; const int &b = num; const int &c = 10;

我們知道,右值往往是沒有名稱的,因此要使用它只能借助引用的方式。這就產生一個問題,實際開發中我們可能需要對右值進行修改(實現移動語義時就需要),顯然左值引用的方式是行不通的

為此,C++11標準引入了另一種引用方式,稱為右值引用,用&&表示

C++標準委員會在選定右值引用符號時,既希望能選用現有 C++ 內部已有的符號,還不能與 C++ 98 /03 標準產生沖突,因此最終選定了 2 個 ‘&’ 表示右值引用。

需要注意的是,和聲明左值引用一樣,右值引用也必須立即進行初始化操作,而且只能使用右值進行初始化,比如:

int num = 10; //int && a = num; //右值引用不能初始化為左值 int && a = 10;

和常量左值引用不同的是,右值引用還可以對右值進行修改。比如:

int && a = 10; a = 100; cout << a << endl;

程序輸出結果為 100。

另外值得一提的是,C++ 語法上是支持定義常量右值引用的,例如:

const int&& a = 10;//編譯器不會報錯

但這種定義出來的右值引用并無實際用處。
一方面,右值引用主要用于移動語義和完美轉發,其中前者需要有修改右值的權限;其次,常量右值引用的作用就是引用一個不可修改的右值,這項工作完全可以交給常量左值引用完成。

引入右值引用的原因除了我們可能需要對右值進行修改,還有另外一個原因,我們來看一個例子:

std::vector<int>foo(){std::vector<int> temp = {1, 2, 3, 4};return temp; }std::vector<int> v = foo();

在這樣的代碼中,就傳統的理解而言,函數foo的返回值temp在內部創建然后被賦值給v,然而v獲得這個對象時,會將整個temp拷貝一份,然后把temp銷毀。如果這個temp非常大,這將造成大量額外的開銷(這也是傳統C++一直被詬病的問題)。在最后一行中,v是左值,foor()返回的值就是右值(也就是純右值),但是,v可以被別的變量俘獲到,而foo()嘗試的那個返回值作為一個臨時值,一旦被v復制后,將立即被銷毀,無法獲取,也不能修改。而將亡值就定義了這一行為:臨時的值能夠被識別、同時也能夠被移動

  • 將亡值,是C++11為了引入右值引用而提出的概念(因此傳統C++中,純右值和右值是同一個概念),也就是即將被銷毀、卻能夠被移動的值

從C++11起,編譯器為我們做了一些工作,此處的temp會被進行此隱式右值轉換,等價于static_cast<std::vector<int>&&>(temp),進而此處的v會將foo局部返回的值進行移動(移動語義

要拿到一個將亡值,就需要用到右值引用:T&&,其中T是類型右值引用的聲明讓這個臨時值的生命周期得以延長,只要變量還活著,那么將網址將繼續存活

C++11提供了std::move這個方法將左值參數無條件的轉換為右值,有了它我們就可以方便的獲得一個右值臨時對象

rv2雖然引用了一個右值,但由于它是一個引用,所以rv2依舊是一個左值

注意,這里有一個歷史遺留問題:

int &a = std::move(1); //不合法,非常量左引用無法引用右值const int &b = std::move(1); // 合法,常量做引用允許引用右值

學到這里,一些讀者可能無法記清楚左值引用和右值引用各自可以引用左值還是右值,這里給大家一張表格,方便大家記憶:

其實,C++11 標準中對右值做了更細致的劃分,分別稱為純右值(Pure value,簡稱 pvalue)和將亡值(eXpiring value,簡稱 xvalue )。其中純右值就是 C++98/03 標準中的右值(本節中已經做了大篇幅的講解),而將亡值則指的是和右值引用相關的表達式(比如某函數返回的 T && 類型的表達式)。對于純右值和將亡值,都屬于右值,讀者知道即可,不必深究。

使用右值引用接管數據

const引用

在C++語言中,引用是作為一種高效、安全的傳遞數據的方式而存在的。除了一般的引用類型,還可以聲明const引用

我們有以下一個Image類。

{ public:Image(int w, int h):width(w), height(h){data = new char[getSize()];}int getSize(){return width * height;} virtual ~Image(){if(data != nullptr){delete data;data = nullptr;width = 0;height = 0;}} private:int width = 0;int height = 0;char* data = nullptr; }

上面只是這個類的雛形,只有析構函數、構造函數和取得數據大小的功能。

接下來編寫比較兩個Image是否相同的函數。最簡單的形式大致如下:

bool isSame(Image& img) {if(width == img.width&& height == img.height){return (memcmp(data,img.data,getSize())==0);}else{return false;} }

這里使用引用類型的參數,避免了沒有必要的拷貝動作。當然我們還可以做的更好:由于比較函數沒有必要也不應該對比較對象的內容進行修改,所以還可以用下面的形式進行承諾:

bool isSame(const Image& img) {if(width == img.width&& height == img.height){char* in = static_cast<char*>(img.data);return (memcmp(data,in,getSize())==0);}else{return false;} }

通過在參數前面增加const修飾符,向isSame方法的調用者保證,不會修改img的內容

右值引用

繼續添加將一個Image的一部分merge到另一個Image上的方法。函數的內容大致如下(這里忽略處理的細節):

void merge(Image& img){//接管img中的數據。img.height = 0;img.width = 0;img.data = nullptr; }

類似的操作在處理在輸入對象時一般有兩種處理方式。有時希望只是參照而不破壞輸入數據,這時可以使用前面講到的為參數增加const修飾符的方式來承諾;有時為了提高效率或者其他的原因希望可以接管輸入的數據,就像上面代碼的狀態。這時的行為更像是數據移動。

對于第二種方式,如果僅僅定義一般的引用類型,利用者根本沒有辦法聲明來確定這個操作是否會接管參數中的數據,這種不確定性會造成恨到的麻煩。

這個時候就可以使用右值引用

void merge(Image&& img){//接管img中的數據。img.height = 0;img.width = 0;img.data = nullptr; }

我們將參數聲明為右值引用,要求像一個臨時變量一樣的使用數據。使用這個函數的方法如下:

Image img1(100, 100); Image img2(100, 200); img1.merge(std::move(img2));

注意代碼中的std::move,這是標準庫中提供的方法,它可以將左值顯式轉換為右值引用類型,從而告訴編譯器,可以向右值(臨時變量)一樣處理它。時也意味著接下來除了對img2賦值或銷毀以外,不再使用它。

C++11通過使用右值引用提供了一種接管數據的方法

總結

如果說使用const修飾符可以對外承諾不對參數進行修改的話,那么使用右值引用就是對外要求接管參數數據的權力

面試題

左值和右值有了解過嗎?

  • 左值是一個內存實體,可以&,可以存在很久
  • 右值沒有內存實體,只是臨時的,用一次就不用了。

可以用std::move將左值轉換為右值

說下你是怎么使用右值引用的

  • 實現一個類的時候,會提供移動構造函數和移動賦值函數
  • 怎么使用:如果發現某個對象需要賦值給一個新對象而且之前老對象不會不用了,就用std::move將左值轉換為右值

總結

以上是生活随笔為你收集整理的C/C++编程:右值引用的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 欧美色图视频在线 | 91丨九色丨海角社区 | 成人av亚洲 | 亚洲精品wwww | 操大逼网站 | 精品一区二区三区不卡 | h狠狠躁死你h高h | 狠狠人妻久久久久久综合蜜桃 | 日韩三级黄 | 成人黄色动漫在线观看 | 亚洲一区二区中文字幕 | 狠狠干在线视频 | 大香依人 | 欧美成人福利 | 曰女同女同中文字幕 | 欧美大片91 | 精品3p | 国产成人观看 | 97人妻精品一区二区三区视频 | 在线观看免费成人 | 免费在线观看成人 | 亚洲一区二区三区av无码 | 美女扒开大腿让男人桶 | 六月婷婷av | 欧美xxxbbb| 成人观看视频 | 成人一二三区 | www.欧美色图| 亚色视频 | 黄色三级片毛片 | 亚洲国产精品久久久久爰色欲 | 高跟肉丝丝袜呻吟啪啪网站av | 欧美一区二区公司 | 久久老熟女一区二区三区 | 亚洲情人网 | 国产精品v亚洲精品v日韩精品 | 亚洲色图 校园春色 | 一级免费观看 | 国产精品自拍一区 | 奶水喷溅 在线播放 | 欧美另类专区 | 日韩伦理视频 | 人人澡超碰碰97碰碰碰 | 日韩精品在线网站 | 国模私拍一区二区 | 日韩欧美在线一区二区 | 爱操综合 | 91九色高潮 | av播放在线 | av网址在线看 | 影音先锋黑人 | 国产精品久久久久久久久久免费看 | 日本在线视频一区二区 | 91叼嘿视频 | 91一区二区在线 | 亚洲色图小说 | 日批视频在线播放 | 香蕉视频一区二区 | 成人性色生活片 | 日本三级影院 | 欧美日韩中文视频 | 久久久精品在线观看 | 特级西西444www大精品视频免费看 | 精久久久久久 | 午夜精品在线播放 | 影音先锋黑人 | 91视频免费在线 | 夜夜天天干 | 久久久久久久久艹 | 欧美xxxxbbbb | 少妇激情视频 | www.在线观看麻豆 | 精品国产露脸精彩对白 | 国产精品视频在 | av网址在线看 | 青娱乐国产 | av免| 日韩欧美偷拍 | 久久久97 | 亚洲伦理视频 | 日韩精品一区中文字幕 | 黄色aa毛片 | 老湿机69福利 | 色偷偷噜噜噜亚洲男人的天堂 | 日韩 国产 一区 | 播播成人网| 国产熟妇一区二区三区四区 | 伊人网狼人 | 国产成人免费av | 手机av观看| 亚洲五码在线 | 成人免费黄色片 | 日日操日日操 | 经典三级第一页 | 99这里都是精品 | 亚洲AV无码成人精品国产一区 | 操日本老妇 | 欧美一级黄 | 午夜h |