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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

Google C++ Coding Style:右值引用(Rvalue Reference)

發布時間:2024/4/13 c/c++ 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Google C++ Coding Style:右值引用(Rvalue Reference) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

右值引用是一個C++11特性,標記為T&&。GSG中定義:只為移動建構函數(Move constructor)和移動賦值操作(Move assignment)使用右值引用。并且不要使用std::Forward(提供的完美轉發特性)。

C++中右值指表達式結束時就不再存的臨時對象。在C++11中,右值分為純右值(即原始字面量,表達式產生的臨時變量等),以及一個將亡值(expiring value, 使用<<深入應用C++11>>中的譯法,指的是與右值引用相關的表達式,如將被移動的對象,T&&函數返回值等)。

以函數返回值表達不出右值引用的威力,因為編譯的本身的優化會解決不必要的對象復制操作。而作為函數參數,如果使用const T&之類的形式也能夠有效避免不必要的對象拷貝。這里特別以與標準容器配合,體現一下,右值引用最大的價值:避免深拷貝。

// 下面一個完整提供了Move Constructor和Move assignment的類。 #include <iostream> #include <string> #include <vector> #include <string.h>class Foo {private:int x = 0;int y = 0;char* strPtr = nullptr;public:Foo() {std::cout << "Constructor was called." << std::endl;}Foo(const char* s) {std::cout << "Constructor with string:" << s << std::endl;if (s != nullptr) {strPtr = new char[strlen(s)];strcpy(strPtr, s);}}// Copy constructorFoo(const Foo& a) : x(a.x),y(a.y) {// Deep copycopyStringValue(a.strPtr);std::cout << "Copy constructor was called." << std::endl;}// Move constructor, no need copy string in deep.Foo(Foo&& a) : x(a.x),y(a.y),strPtr(a.strPtr) {a.strPtr = nullptr; // 注意要清掉之前的字串,這樣才是移動。std::cout << "Move constructor was called." << std::endl;}Foo& operator=(const Foo& a) {x = a.x;y = a.y;copyStringValue(a.strPtr);std::cout << "Assignment Operator was called." << std::endl;}~Foo() {if (strPtr != nullptr) {std::cout << "Free allocated string:" << strPtr << std::endl;delete strPtr;}std:: cout << "Deconstructor was called." << std::endl;}private:void copyStringValue(const char* s) {if (strPtr != nullptr) {delete strPtr;strPtr = nullptr;}if (s != nullptr) {strPtr = new char[strlen(s)];strcpy(strPtr, s);}} };int main(void) {{std::cout << "Need to clear string twice:" << std::endl;std::vector<Foo> myVec;Foo a("Instance A");myVec.push_back(a);}std::cout << "============" << std::endl;{std::cout << "Only need to clear string one time:" << std::endl;std::vector<Foo> myVec;Foo c("Instance C");myVec.push_back(std::move(c));}std::cout << "============" << std::endl;{Foo d("Instance D");Foo x = d;}std::cout << "============" << std::endl;{Foo e("Instance E");Foo&& y = std::move(e);} }

觀察代碼刪除字串的次數,就可以了解右值引用的作用了。程序運行的輸出如下:

Need to clear string twice: Constructor with string:Instance A Copy constructor was called. Free allocated string:Instance A Deconstructor was called. Free allocated string:Instance A Deconstructor was called. ============ Only need to clear string one time: Constructor with string:Instance C Move constructor was called. Deconstructor was called. Free allocated string:Instance C Deconstructor was called. ============ Constructor with string:Instance D Copy constructor was called. Free allocated string:Instance D Deconstructor was called. Free allocated string:Instance D Deconstructor was called. ============ Constructor with string:Instance E Free allocated string:Instance E Deconstructor was called.

但是考慮到右值引用中的引用折疊(reference collapsing)會引入一些復雜度(左右值的轉換規則),造成理解上的問題,所以將右值引用的應用范圍做了如開篇所說的限定。

在實際應用中,會出現沒有直接定義類型的右值引用,被稱為universal reference,需要進行類型推導。另一種情況是使用auto &&定義的也是universal reference。

關于std::forward,它被稱為完美轉發(Perfect Forwarding)。要解決的問題是在函數模板中,完全依照模板的參數的類型,保持參數的左值,右值特征),將參數傳遞給函數模板中調用的另一個函數(轉自<<深入應用C++11>>)。根據這個定義,完美轉發僅針對需要調用內部實現的模板函數,而且需要開發者識別出哪些情況是有效的,而哪些情況下又是無效的。比如適用的場景:

template<class T> void foo(T&& arg) {// 如下保持arg的類型傳入到bar()中bar(std::forward<T>(arg)); }

但如果內部函數無需要針對左值或右值做特殊處理,這種場景是不需要轉發的。參考:When not to use std::forward。

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

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

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