std move和右值引用

2021-08-08 16:33:29 字數 1706 閱讀 4880

右值引用允許程式設計人員去避免不必要的記憶體拷貝,從而提高效能。

我們知道如果乙個類a的成員變數中有指標,那麼就要考慮深拷貝和淺拷貝了,深拷貝通常要實現下面幾個函式:

* 建構函式

* 拷貝構造

* 賦值操作符

這樣做是沒問題的,但是會帶來乙個問題,會造成一些沒必要的拷貝,如:

std::string str("hello");

str.resize(1024 * 1024 * 100);

std::vector

v;v.push_back(str);

str這裡故意給它分配了100m,把它push到vector中的時候其實又做了一次額外的拷貝(也就是深拷貝),

我們通過任務管理器中的記憶體也可以看出來有200多兆了,拷貝是非常高昂的開銷,使用下面方法來解決這個問題:

std::string str("hello");

str.resize(1024 * 1024 * 100);

std::vector

v;v.push_back(std::move(str));

我們再通過任務管理器看程式執行後的記憶體大小發現就100兆多一點,說明上面方法避免了深拷貝。

其實它是用了類似淺拷貝的方式直接把str中的記憶體位址給拷貝過來了,同時把str指向nullptr,所以,此時

列印str的內容發現它是空的。這樣做是非常有必要的,否則兩個指標指向同一塊記憶體會造成更嚴重的危害,

況且std::move通常針對的是右值(相當於臨時值),所以move之後我們不太可能會再去使用它。

上面我們就加了乙個std::move就有這麼大的優化,看起來很容易的。

其實不然,因為我演示用的是stl中的string在c++11中它自身就支援右值引用

擷取一段原始碼,&&就是右值引用

basic_string(_myt&& _right) _noexcept

: _mybase(_right._getal())

所以,如果是我們自定義的類要想使用右值引用就要像實現拷貝構造,賦值操作符那樣去實現右值引用了,舉個例子:

template

class clone_ptr

// 析構函式

~clone_ptr()

// 拷貝構造

clone_ptr(const clone_ptr& p)

: ptr(p.ptr ? p.ptr->clone() : 0)

{}// 賦值操作符

clone_ptr& operator=(const clone_ptr& p)

return *this;

}// 拷貝構造,move語法,右值引用

clone_ptr(clone_ptr&& p)

: ptr(p.ptr)

// 賦值操作符,move語法,右值引用

clone_ptr& operator=(clone_ptr&& p)

// other operations

t& operator*() const

// ...

};

std::move只是返回乙個右值型別,從而呼叫類中實現的對右值的操作。所以關鍵還是類的實現,對寫庫的人而言增加了工作量,

但是對使用者而言還是很容易使用的,而且極大的提高了程式效能。

C 11 右值引用以及std move

int和int 是什麼?都是型別。int是整數型別,int 則是整數引用型別。相同int 也是乙個型別。兩個引號 是c 11提出的乙個新的引用型別。記住,這是乙個新的型別。默念 10次吧。假設你記住這個新型別,那麼非常多疑問都能迎刃而解。而且對 effective modern c 說到的void ...

C 11右值引用和std move語句例項解析

關鍵字 c 11,右值引用,rvalue,std move,vs 2015 os windows 10 右值引用 及其支援的move語意和完美 是c 0x加入的最重大語言特性之一。從實踐角度講,它能夠完美解決c 中長久以來為人所詬病的臨時物件效率問題。從語言本身講,它健全了c 中的引用型別在左值右值...

左值和右值,左值引用和右值引用

左值 lvalue 這一術語 於c語言,用來指代那些可以用在賦值表示式左側的東西,具名物件 在棧和堆上分配的物件,或者其他物件的成員,總之就是又確定儲存空間的東西。而術語右值 rvalue 也是源自c語言,指的是只能在賦值表示式右側出現的東西,如字面值和臨時物件。只能繫結到左值,不能繫結到右值的引用...