第二章的內容:主講右值引用
1、左值和右值區分的判據是看是否可對表示式用&取址,左值可以,右值不可以
//1、左值引用相當於給變數起個別名,故必須是變數,而不能是常量
int aa = 1;
int &b = aa;//ok
int &k = 2;//error 必須為左值
//2、右值引用
int&& a = 1; //ok,實質上就是給不具名(匿名)變數起個別名
int b = 1;
int && c = b; //error! 不能將乙個左值賦值給乙個右值引用
2、移動構造和移動賦值
傳統的左值操作會開銷很大的記憶體,比如在深拷貝建構函式中,對某變數進行拷貝賦值時,需重新申請一塊記憶體對其進行賦值
#include #include #include using namespace std;
class mystring
else
} // 拷貝建構函式
mystring(const mystring& str)
// 移動建構函式
mystring(mystring&& str)
:m_data(str.m_data)
// 拷貝賦值函式 =號過載
mystring& operator=(const mystring& str)
// 移動賦值函式 =號過載
mystring& operator=(mystring&& str)
~mystring()
char* get_c_str() const
private:
char* m_data;
};size_t mystring::cctor = 0;
size_t mystring::mctor = 0;
size_t mystring::casgn = 0;
size_t mystring::masgn = 0;
int main()
cout << "cctor = " << mystring::cctor << endl;
cout << "mctor = " << mystring::mctor << endl;
cout << "casgn = " << mystring::casgn << endl;
cout << "masgn = " << mystring::masgn << endl;
}
移動建構函式與拷貝構造不同,它並不是重新分配一塊新的空間,將要拷貝的物件複製過來,而是"偷"了過來,將自己的指標指向別人的資源,這就節省了記憶體開銷,然後將別人的指標修改為nullptr
,這一步很重要,如果不將別人的指標修改為空,那麼臨時物件析構的時候就會釋放掉這個資源,"偷"也白偷了。下面這張圖可以解釋copy和move的區別:
2、move的作用是將乙個左值強制轉換為乙個右值引用,我們可以通過右值引用來使用該值,以用於移動建構函式,消減記憶體開銷
mystring str1("hello"); //呼叫建構函式
mystring str2(str1); //呼叫拷貝建構函式
mystring str3(std::move(str1)); // 呼叫移動建構函式
3、emplace_back取代push_back
emplace_back沒有記憶體的移動,可以節省中間變數的記憶體開銷,建議多使用emplace_back
struct a
};int main()
; vec.emplace_back(a);
vec.emplace(vec.begin(), a);
cout << vec.size() << endl;
cout << vec.at(1).y << endl;
}
c 11 右值引用
右值引用 是一種復合型別,跟c 的傳統引用很類似。為更準確地區分兩種型別,我們把傳統的c 引用稱為 左值引用 而使用 引用 這一術語時,我們的意思同時包含兩種引用 左值引用和右值引用。右值引用的行為跟左值引用類似,不同之處在於 右值引用可以繫結到臨時量 右值 而 非const的 左值引用卻不能繫結到...
C 11 右值引用
消除兩個物件互動時不必要的物件拷貝,節省運算儲存資源,提高效率。能夠更簡潔明確地定義泛型函式。1.右值引用 int a a 1 here,a is an lvalue 上述的a就是乙個左值。c 11中左值的宣告符號為 為了和左值區分,右值的宣告符號為 printreference const str...
C 11右值引用
c 11中引入的乙個非常重要的概念就是右值引用。理解右值引用是學習 移動語義 move semantics 的基礎。而要理解右值引用,就必須先區分左值與右值。對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物...