香蕉视频国产在线_西野翔中文久久精品国产_国产成人在线小视频_欧美日韩一区三区_日韩福利影视_久久久无码精品亚洲国产_成人h在线播放_国产精品网友自拍_成年人在线免费观看_www.69av

全國服務熱線:0551-64931480

11
20-01

C++11中的 右值引用與轉移語義

云庫科技 769224 0

新特性的目的

右值引用 (Rvalue Referene) 是 C++ 新標準 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它實現了轉移語義 (Move Sementics) 和精確傳遞 (Perfect Forwarding)。它的主要目的有兩個方面:

消除兩個對象交互時不必要的對象拷貝,節省運算存儲資源,提高效率。
能夠更簡潔明確地定義泛型函數。

左值與右值的定義

C++( 包括 C) 中所有的表達式和變量要么是左值,要么是右值。通俗的左值的定義就是非臨時對象,那些可以在多條語句中使用的對象。所有的變量都滿足這個定義,在多條代碼中都可以使用,都是左值。右值是指臨時的對象,它們只在當前的語句中有效。請看下列示例 :

簡單的賦值語句

如:int i = 0;
在這條語句中,i 是左值,0 是臨時值,就是右值。在下面的代碼中,i 可以被引用,0 就不可以了。立即數都是右值。

右值也可以出現在賦值表達式的左邊,但是不能作為賦值的對象,因為右值只在當前語句有效,賦值沒有意義。
如:((i>0) ? i : j) = 1;

在這個例子中,0 作為右值出現在了”=”的左邊。但是賦值對象是 i 或者 j,都是左值。

在 C++11 之前,右值是不能被引用的,最大限度就是用常量引用綁定一個右值,如 :

const int &a = 1;

在這種情況下,右值不能被修改的。但是實際上右值是可以被修改的,如 :

T().set().get();

T 是一個類,set 是一個函數為 T 中的一個變量賦值,get 用來取出這個變量的值。在這句中,T() 生成一個臨時對象,就是右值,set() 修改了變量的值,也就修改了這個右值。

既然右值可以被修改,那么就可以實現右值引用。右值引用能夠方便地解決實際工程中的問題,實現非常有吸引力的解決方案。

左值和右值的語法符號

左值的聲明符號為”&”, 為了和左值區分,右值的聲明符號為”&&”。

示例程序 :

void process_value(int& i) { 
 std::cout << "LValue processed: " << i << std::endl; 
} 
 
void process_value(int&& i) { 
 std::cout << "RValue processed: " << i << std::endl; 
} 
 
int main() { 
 int a = 0; 
 process_value(a); 
 process_value(1); 
}

運行結果 :

LValue processed: 0 
RValue processed: 1

Process_value 函數被重載,分別接受左值和右值。由輸出結果可以看出,臨時對象是作為右值處理的。

但是如果臨時對象通過一個接受右值的函數傳遞給另一個函數時,就會變成左值,因為這個臨時對象在傳遞過程中,變成了命名對象。

示例程序 :

void process_value(int& i) { 
 std::cout << "LValue processed: " << i << std::endl; 
} 
 
void process_value(int&& i) { 
 std::cout << "RValue processed: " << i << std::endl; 
} 
 
void forward_value(int&& i) { 
 process_value(i); 
} 
 
int main() { 
 int a = 0; 
 process_value(a); 
 process_value(1); 
 forward_value(2); 
}

運行結果 :

LValue processed: 0 
RValue processed: 1 
LValue processed: 2

雖然 2 這個立即數在函數 forward_value 接收時是右值,但到了 process_value 接收時,變成了左值。

轉移語義的定義

右值引用是用來支持轉移語義的。轉移語義可以將資源 ( 堆,系統對象等 ) 從一個對象轉移到另一個對象,這樣能夠減少不必要的臨時對象的創建、拷貝以及銷毀,能夠大幅度提高 C++ 應用程序的性能。臨時對象的維護 ( 創建和銷毀 ) 對性能有嚴重影響。

轉移語義是和拷貝語義相對的,可以類比文件的剪切與拷貝,當我們將文件從一個目錄拷貝到另一個目錄時,速度比剪切慢很多。

通過轉移語義,臨時對象中的資源能夠轉移其它的對象里。

在現有的 C++ 機制中,我們可以定義拷貝構造函數和賦值函數。要實現轉移語義,需要定義轉移構造函數,還可以定義轉移賦值操作符。對于右值的拷貝和賦值會調用轉移構造函數和轉移賦值操作符。如果轉移構造函數和轉移拷貝操作符沒有定義,那么就遵循現有的機制,拷貝構造函數和賦值操作符會被調用。

普通的函數和操作符也可以利用右值引用操作符實現轉移語義。

實現轉移構造函數和轉移賦值函數

以一個簡單的 string 類為示例,實現拷貝構造函數和拷貝賦值操作符。

示例程序 :

class MyString { 
private: 
 char* _data; 
 size_t   _len; 
 void _init_data(const char *s) { 
   _data = new char[_len+1]; 
   memcpy(_data, s, _len); 
   _data[_len] = '\0'; 
 } 
public: 
 MyString() { 
   _data = NULL; 
   _len = 0; 
 } 
 
 MyString(const char* p) { 
   _len = strlen (p); 
   _init_data(p); 
 } 
 
 MyString(const MyString& str) { 
   _len = str._len; 
   _init_data(str._data); 
   std::cout << "Copy Constructor is called! source: " << str._data << std::endl; 
 } 
 
 MyString& operator=(const MyString& str) { 
   if (this != &str) { 
     _len = str._len; 
     _init_data(str._data); 
   } 
   std::cout << "Copy Assignment is called! source: " << str._data << std::endl; 
   return *this; 
 } 
 
 virtual ~MyString() { 
   if (_data) free(_data); 
 } 
}; 
 
int main() { 
 MyString a; 
 a = MyString("Hello"); 
 std::vector<MyString> vec; 
 vec.push_back(MyString("World")); 
}

運行結果 :

Copy Assignment is called! source: Hello 
Copy Constructor is called! source: World

這個 string 類已經基本滿足我們演示的需要。在 main 函數中,實現了調用拷貝構造函數的操作和拷貝賦值操作符的操作。MyString(“Hello”) 和 MyString(“World”) 都是臨時對象,也就是右值。雖然它們是臨時的,但程序仍然調用了拷貝構造和拷貝賦值,造成了沒有意義的資源申請和釋放的操作。如果能夠直接使用臨時對象已經申請的資源,既能節省資源,有能節省資源申請和釋放的時間。這正是定義轉移語義的目的。

我們先定義轉移構造函數。

MyString(MyString&& str) { 
   std::cout << "Move Constructor is called! source: " << str._data << std::endl; 
   _len = str._len; 
   _data = str._data; 
   str._len = 0; 
   str._data = NULL; 
}

和拷貝構造函數類似,有幾點需要注意:

  1. 參數(右值)的符號必須是右值引用符號,即“&&”。

  2. 參數(右值)不可以是常量,因為我們需要修改右值。

  3. 參數(右值)的資源鏈接和標記必須修改。否則,右值的析構函數就會釋放資源。轉移到新對象的資源也就無效了。

現在我們定義轉移賦值操作符。

MyString& operator=(MyString&& str) { 
   std::cout << "Move Assignment is called! source: " << str._data << std::endl; 
   if (this != &str) { 
     _len = str._len; 
     _data = str._data; 
     str._len = 0; 
     str._data = NULL; 
   } 
   return *this; 
}

這里需要注意的問題和轉移構造函數是一樣的。

增加了轉移構造函數和轉移復制操作符后,我們的程序運行結果為 :

Move Assignment is called! source: Hello 
Move Constructor is called! source: World

由此看出,編譯器區分了左值和右值,對右值調用了轉移構造函數和轉移賦值操作符。節省了資源,提高了程序運行的效率。

有了右值引用和轉移語義,我們在設計和實現類時,對于需要動態申請大量資源的類,應該設計轉移構造函數和轉移賦值函數,以提高應用程序的效率。

標準庫函數 std::move

既然編譯器只對右值引用才能調用轉移構造函數和轉移賦值函數,而所有命名對象都只能是左值引用,如果已知一個命名對象不再被使用而想對它調用轉移構造函數和轉移賦值函數,也就是把一個左值引用當做右值引用來使用,怎么做呢?標準庫提供了函數 std::move,這個函數以非常簡單的方式將左值引用轉換為右值引用。

示例程序 :

void ProcessValue(int& i) { 
 std::cout << "LValue processed: " << i << std::endl; 
} 
 
void ProcessValue(int&& i) { 
 std::cout << "RValue processed: " << i << std::endl; 
} 
 
int main() { 
 int a = 0; 
 ProcessValue(a); 
 ProcessValue(std::move(a)); 
}

運行結果 :

LValue processed: 0 
RValue processed: 0

std::move在提高 swap 函數的的性能上非常有幫助,一般來說,swap函數的通用定義如下:

template <class T> swap(T& a, T& b) 
{ 
       T tmp(a);   // copy a to tmp 
       a = b;      // copy b to a 
       b = tmp;    // copy tmp to b 
}

有了 std::move,swap 函數的定義變為 :

template <class T> swap(T& a, T& b) 
{ 
       T tmp(std::move(a)); // move a to tmp 
       a = std::move(b);    // move b to a 
       b = std::move(tmp);  // move tmp to b 
}

通過 std::move,一個簡單的 swap 函數就避免了 3 次不必要的拷貝操作。

精確傳遞 (Perfect Forwarding)

本文采用精確傳遞表達這個意思。”Perfect Forwarding”也被翻譯成完美轉發,精準轉發等,說的都是一個意思。

精確傳遞適用于這樣的場景:需要將一組參數原封不動的傳遞給另一個函數。

“原封不動”不僅僅是參數的值不變,在 C++ 中,除了參數值之外,還有一下兩組屬性:

左值/右值和 const/non-const。 精確傳遞就是在參數傳遞過程中,所有這些屬性和參數值都不能改變。在泛型函數中,這樣的需求非常普遍。

下面舉例說明。函數 forward_value 是一個泛型函數,它將一個參數傳遞給另一個函數 process_value。

forward_value 的定義為:

template <typename T> void forward_value(const T& val) { 
 process_value(val); 
} 
template <typename T> void forward_value(T& val) { 
 process_value(val); 
}

函數 forward_value 為每一個參數必須重載兩種類型,T& 和 const T&,否則,下面四種不同類型參數的調用中就不能同時滿足 :

int a = 0; 
 const int &b = 1; 
 forward_value(a); // int& 
 forward_value(b); // const int& 
forward_value(2); // int&

對于一個參數就要重載兩次,也就是函數重載的次數和參數的個數是一個正比的關系。這個函數的定義次數對于程序員來說,是非常低效的。我們看看右值引用如何幫助我們解決這個問題 :

template <typename T> void forward_value(T&& val) { 
 process_value(val); 
}

只需要定義一次,接受一個右值引用的參數,就能夠將所有的參數類型原封不動的傳遞給目標函數。四種不用類型參數的調用都能滿足,參數的左右值屬性和 const/non-cosnt 屬性完全傳遞給目標函數 process_value。這個解決方案不是簡潔優雅嗎?

int a = 0; 
const int &b = 1; 
forward_value(a); // int& 
forward_value(b); // const int& 
forward_value(2); // int&&

C++11 中定義的 T&& 的推導規則為:

右值實參為右值引用,左值實參仍然為左值引用。

一句話,就是參數的屬性不變。這樣也就完美的實現了參數的完整傳遞。

右值引用,表面上看只是增加了一個引用符號,但它對 C++ 軟件設計和類庫的設計有非常大的影響。它既能簡化代碼,又能提高程序運行效率。每一個 C++ 軟件設計師和程序員都應該理解并能夠應用它。我們在設計類的時候如果有動態申請的資源,也應該設計轉移構造函數和轉移拷貝函數。在設計類庫時,還應該考慮 std::move 的使用場景并積極使用它。

總結

右值引用和轉移語義是 C++ 新標準中的一個重要特性。每一個專業的 C++ 開發人員都應該掌握并應用到實際項目中。在有機會重構代碼時,也應該思考是否可以應用新也行。在使用之前,需要檢查一下編譯器的支持情況。

評論列表(0)
暫無評論
日韩精选在线观看| 91精品国产欧美一区二区| 欧美午夜女人视频在线| 91精选在线观看| 亚洲毛茸茸少妇高潮呻吟| 欧美福利小视频| 91在线观看免费高清| 水蜜桃一区二区| 六月丁香婷婷激情| 大尺度做爰床戏呻吟舒畅| 亚洲天堂黄色片| 伊人久久成人网| 日韩av高清在线| 狂野欧美性猛交xxxxx视频| 久久久久久亚洲精品美女 | 日韩国产精品视频| 欧美精品激情在线| 国产精品免费一区二区三区在线观看 | 丰满大乳少妇在线观看网站| 不卡一区视频| 中国精品18videos性欧美| 精品夜夜嗨av一区二区三区| 国产精品久久久久三级| 欧美日韩高清影院| 久久伊人精品天天| 99蜜桃在线观看免费视频网站| 日韩不卡视频一区二区| 丰满少妇xbxb毛片日本| 久久免费公开视频| 婷婷在线观看视频| 国产乱码精品一区二三赶尸艳谈| 色综合www| 久久一区中文字幕| 国产精品久久国产精麻豆99网站| 欧美精品久久久久久久久老牛影院| 久久精品国产99国产精品澳门| 草莓视频成人appios| 国产成人a视频高清在线观看| 欧美日韩伦理| 国产一区二区在线影院| 亚洲电影一区二区三区| 亚洲美女自拍视频| 国产色综合天天综合网| aa视频在线播放| 国产黄色大片免费看| 国产精品人妻一区二区三区| 日韩毛片久久久| 麻豆国产精品| 久久久成人网| 亚洲免费看黄网站| 日韩久久精品成人| 国产精品视频区| 久久这里只有精品18| 亚洲精品视频久久久| 最近中文字幕在线观看视频| 黄色网页在线免费观看| 久久亚洲黄色| 麻豆成人免费电影| 亚洲超碰精品一区二区| 伊人久久精品视频| 岛国视频一区| 亚洲成人福利在线| 日本va欧美va国产激情| 高清性色生活片在线观看| 亚洲精选av| 乱一区二区av| 日韩欧美在线观看| 欧美黑人巨大xxx极品| 亚洲精品二区| 黄色在线观看av| 成人福利小视频| 在线毛片观看| 狠狠88综合久久久久综合网| 中文字幕中文字幕一区| 亚洲欧美国产va在线影院| 99久久精品免费看国产四区| 69久久久久久| 中文字幕69页| 国产美女情趣调教h一区二区| 日韩欧美精品| 国产亚洲精品超碰| 日韩精品在线观看视频| 丁香五月网久久综合| 欧美视频亚洲图片| 中文字幕日韩三级| 国产免费不卡| 亚洲综合日本| 狠狠爱在线视频一区| 欧美另类高清videos| 在线视频不卡一区二区三区| 欧美人与性囗牲恔配| 一级在线免费观看| 一区二区三区自拍视频| 国产精品1024| 精品99999| 国产在线一区二区三区播放| 日本一区二区在线免费观看| 日本免费一区视频| 136福利精品导航| 国产91精品在线观看| 欧美电影精品一区二区| 成人午夜电影免费在线观看| 波多野结衣中文字幕在线播放| 99久久亚洲精品日本无码| 唐人社导航福利精品| 日日摸夜夜添夜夜添国产精品| 色八戒一区二区三区| 国产精品xxxxx| 浓精h攵女乱爱av| 国产人妖在线播放| 91久久青草| 成人午夜精品在线| 日韩国产欧美精品一区二区三区| 日本高清一区| 中文字幕亚洲欧美日韩| 免费观看在线黄色网| 午夜欧美理论片| 精品人伦一区二区三区蜜桃网站| 日本一区二区不卡| 超碰人人草人人| 色婷婷在线视频| 婷婷成人在线| 亚洲人成伊人成综合网小说| 久久久久久久999| 欧美三级理论片| 亚洲第一天堂影院| 成人三级av在线| 日本一区二区三级电影在线观看 | 国产精品欧美精品| 久久69精品久久久久久国产越南| 免费人成自慰网站| 在线观看亚洲一区二区| 精品亚洲a∨一区二区三区18| 91麻豆精品秘密| 欧美大胆在线视频| 日韩大片一区二区| 天天操天天干天天爽| 国产一区不卡| 天天影视网天天综合色在线播放| 川上优av一区二区线观看| 国产传媒第一页| 999亚洲国产精| 自拍偷拍精品| 在线天堂资源www在线污| 精品人人视频| 国产一区欧美一区| 久久夜色精品国产噜噜av小说| 国产区在线观看成人精品| 久久久久久com| 中文字幕avav| 国产精品99999| 久久成人在线| 日韩精品在线视频| 国产精品12345| 手机av免费在线观看| 欧美电影免费观看高清| 欧美撒尿777hd撒尿| 秋霞久久久久久一区二区| 天天综合网入口| 99re6热只有精品免费观看| 亚洲视频一区在线观看| 国产一区二区在线免费| 亚洲欧美另类日本| 成人做爰视频www网站小优视频| 99精品国产视频| 91国在线精品国内播放| 国产精品九九九九九| 成人三级小说| 97se亚洲国产综合自在线| 66m—66摸成人免费视频| 中文文字幕文字幕高清| 性欧美1819sex性高清大胸| 国产精品一级在线| 久久久久久久久久久亚洲| 中文字幕在线视频播放| ****av在线网毛片| 久久久久久久久久久电影| 国产精品黄视频| 日本一级二级视频| 亚洲精品国产无套在线观| 亚洲精品福利免费在线观看| 免费在线观看视频a| 亚洲色图欧美视频| 中文日韩欧美| 国产一区二区三区在线视频| 黄色手机在线视频| 成人p站proumb入口| 久色婷婷小香蕉久久| 九九九热精品免费视频观看网站| 欧美夫妇交换xxx| 理论不卡电影大全神| 中文字幕av资源一区| 91福利入口| 啪啪小视频网站| 日韩精品不卡一区二区| 精品国产免费一区二区三区四区 | 18加网站在线| 国产午夜精品一区二区三区嫩草 | 黄色片在线播放| 国产成人免费高清| 国产成人久久久精品一区| 国产免费无码一区二区视频| 51亚洲精品| 欧美日韩精品专区| 99爱视频在线| 91高清在线| 久久影院视频免费| 高清免费日韩| 夜夜狠狠擅视频| 国内精品嫩模av私拍在线观看| 亚洲一级一级97网| 插我舔内射18免费视频| 欧美日韩尤物久久| 色乱码一区二区三区88| 欧美乱大交xxxxx潮喷l头像| 91ph在线| 欧美极品xxx| 欧美日韩国产精品一区二区| 亚洲美女性生活| 麻豆精品新av中文字幕| 国产精品69精品一区二区三区| 亚洲精品在线观看av| 不卡一区2区| 国产亚洲欧美aaaa| 无码国产69精品久久久久同性| 视频欧美一区| 欧美一区二区视频在线观看2022| 9l视频白拍9色9l视频| 美女搞黄视频在线观看| 香蕉久久一区二区不卡无毒影院| 国产91在线亚洲| 四虎久久免费| 中文字幕亚洲精品在线观看| 亚洲精品视频一二三| 麻豆av电影在线观看| 亚洲色图色老头| 久久爱av电影| 神马午夜一区二区| 国产乱人伦偷精品视频免下载| 国产免费一区二区三区香蕉精| 中文亚洲av片在线观看| 亚洲一区区二区| 国产不卡精品视男人的天堂| 久久久久久久亚洲| 一区二区三区四区五区精品视频| 7777免费精品视频| 毛片基地在线观看| 国产视频久久| 国产精品久久久久aaaa九色| 亚洲一区二区三区高清视频| 欧美a级一区二区| 成人免费在线视频网站| aaa一区二区三区| 国产成人综合亚洲91猫咪| 国产区欧美区日韩区| 宅男午夜在线| 久久久久久亚洲综合| 亚洲一区二区三区精品视频| 午夜在线小视频| 一区二区高清在线| 日韩网址在线观看| 电影一区电影二区| 欧美电视剧在线看免费| 老牛影视av老牛影视av| 九九在线高清精品视频| 久久天堂电影网| 天堂中文在线网| 蜜桃91丨九色丨蝌蚪91桃色| 98国产高清一区| 未来日记在线观看| 综合久久一区二区三区| 无码aⅴ精品一区二区三区浪潮 | 免费在线观看a视频| 999久久久亚洲| 欧美一级大片在线免费观看| 亚洲熟妇av乱码在线观看| 国产乱码字幕精品高清av| 欧美日韩精品免费在线观看视频| 国产在线电影| 亚洲国产乱码最新视频| 国产欧美激情视频| 日韩精品免费一区二区夜夜嗨| 久久久精品免费| 国产99久久久久久免费看| 国产一区中文字幕| 亚洲 国产 欧美一区| 欧美理论片在线播放| 欧美精品久久一区| 成人在线观看免费高清| 亚洲高清电影| 99免费在线视频观看| 国产三级电影在线| 色综合欧美在线视频区| 成人性生活免费看| 国产精品成人av| 国产中文字幕亚洲| 欧美日本网站| 一本大道久久a久久精二百| 菠萝菠萝蜜网站| 欧美va天堂在线| 亚洲va久久久噜噜噜久久天堂| 欧美成人综合在线| 欧美日韩国产在线看| jizz欧美性20| 精久久久久久| 久久99精品久久久久久秒播放器| 成人短视频在线| 日韩一级片网站| 九九热精品在线观看| 激情欧美日韩一区二区| 午夜啪啪福利视频| 91成人抖音| www.亚洲成人| 精品国产亚洲av麻豆| 国产精品不卡一区二区三区| 色婷婷激情视频| 亚洲九九视频| 国产精品区一区二区三在线播放 | 不卡一区2区| 7777奇米亚洲综合久久| 日本免费在线视频| 日韩精品一区二区三区视频播放 | 深爱激情五月婷婷| 午夜婷婷国产麻豆精品| 91成年人网站| 日韩影院在线观看| 亚洲图片都市激情| 成人在线高清| 色综合视频网站| 情趣视频网站在线免费观看| 欧美视频裸体精品| 制服丨自拍丨欧美丨动漫丨| 韩国一区二区视频| 日韩av综合在线观看| 图片婷婷一区| 亚洲精品欧美日韩专区| 黑人极品ⅴideos精品欧美棵| 亚洲欧美日韩精品久久奇米色影视 | 99精品综合| 精品产品国产在线不卡| 日本综合久久| 久久久亚洲国产| 国产在线视频资源| 日韩精品一区二区三区中文不卡| 亚洲图片在线视频| 国产精品热久久久久夜色精品三区| 无码人妻少妇色欲av一区二区| 今天的高清视频免费播放成人| 亚洲欧洲一区二区| www.神马久久| 成人做爽爽免费视频| 国产社区精品视频| 欧美噜噜久久久xxx| 日韩欧美亚洲系列| 精品乱码亚洲一区二区不卡| 7777久久亚洲中文字幕| 亚洲国产精品一区二区久久| 亚洲一级生活片| xnxx国产精品| 男男做爰猛烈叫床爽爽小说| 久久99精品一区二区三区| 人妻内射一区二区在线视频| 自拍视频亚洲| 一区二区三视频| 自拍视频一区| 久久久久久久久一区| 麻豆国产精品| 3d蒂法精品啪啪一区二区免费| 国产免费不卡| 日本不卡免费高清视频| 国产蜜臀av在线播放| 久久97精品久久久久久久不卡| 最新国产在线观看| 在线日韩精品视频| 日本大片在线观看| 日韩精品中文字幕视频在线| 亚洲 欧美 激情 另类| 91麻豆精品国产自产在线观看一区| 91在线观看喷潮| 日本高清视频一区二区| 欧美男人亚洲天堂| 欧美性猛交xxxx乱大交极品| www欧美在线| 精品国产91久久久| 91丝袜一区二区三区| 亚洲电影一级黄| 欧美h在线观看| 精品久久久久久中文字幕大豆网| 亚洲天堂一区在线观看| 精品久久久久久久久国产字幕| yjizz国产| 欧美午夜片在线免费观看| 中文字幕免费观看| 在线欧美小视频| 国产伦精品一区二区三区四区| 欧美色区777第一页| 97caocao| 日韩美女在线视频| 中文字幕在线视频不卡| 亚洲深夜福利视频|