C++11:move移动语义
前言
我們知道移動語義是通過右值引用來匹配臨時值,那么,普通的左值是否也能借助移動語義來優化性能呢,C++11為了解決這個問題,提供了std::move方法來將左值轉換成右值。
正文
move是將對象的狀態或者所有權從一個對象轉移到另一個對象,只是轉移,沒有內存拷貝。
move實際上并不能移動任何東西,它只是將一個左值強制轉換成一個右值引用,使我們可以通過右值引用使用該值,以用于移動語義,強制轉換為右值的目的是為了方便實現移動構造。
這種move語義是很有用的,比如一個對象中有一些指針資源或者動態數組,在對象的賦值或者拷貝時就不需要拷貝這些資源了。在C++11之前拷貝構造函數和賦值函數可能要像下面這樣定義。假設A對象內部有一個資源m_ptr:
A & A::operator=(const A &rhs) { //銷毀m_ptr指向的資源 //復制rhs.m_ptr所指向的資源,并使m_ptr指向它 }通過A的拷貝構造函數也是這樣,假設這樣來使用A:
A foo(); A a; a = foo();最后一行將會發生如下操作:
- 銷毀a所持有的資源
- 復制foo返回的臨時對象所擁有的資源
- 銷毀臨時對象,釋放其資源
上面的辦法是可行的,但是更有效的方法是直接交換a和臨時對象中的資源指針,然后讓臨時對象的析構函數去銷毀a原來擁有的資源。當復制操作符的右邊是右值的時候,我們希望賦值操作符被定義成下面這樣:
A & A::operator=(const A &&rhs) { //轉移資源的控制權,無需復制 }僅僅轉移資源的所有者,將資源的擁有者改為被賦值者,這就是move語義。
如下示例,假設一個臨時容器很大,賦值給另一個容器:
{std::list<std::string> arrs; //省略初始化std::list<std::string> temp = arrs; }std::list<std::string> arrs; std::list<std::string> temp = std::move(arrs);如果這里不用move,拷貝的代價很大,性能較低。而使用move幾乎沒有任何代價,只是將資源的所有權轉移了,實際上是將左值變成了右值引用,然后應用move語義調用構造函數,這樣避免了拷貝,提高程序性能。
當一個對象內部有較大的堆內存或者動態數組時,很有必要寫move語義的拷貝構造函數和賦值函數,避免無謂的深拷貝,以提高性能。
注意:move對于擁有形如對內存、文件句柄等子資源的成員的對象有效,如果是一些基本類型, 如int和char[4]數組時,如果使用move,仍然會發生拷貝(因為沒有對應的移動構造函數),所以說move對于含資源的對象來說更有意義。
參考:《深入應用C++11》
總結
以上是生活随笔為你收集整理的C++11:move移动语义的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Coding:在数组中查找具有给定总和的
- 下一篇: C++之仿函数简介