C++中什么時候使用std::move?

這篇文章主要講解了“C++中什么時候使用std::move”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“C++中什么時候使用std::move”吧!

在玉龍等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站建設(shè)、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作定制網(wǎng)站,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計,全網(wǎng)營銷推廣,成都外貿(mào)網(wǎng)站制作,玉龍網(wǎng)站建設(shè)費用合理。

ES.56:只在需要將一個對象顯式移動到另外的作用域時使用std::move

Reason(原因)

我們使用move而不是copy是為了避免不必要的重復(fù)并提高性能。

移動操作一般會留下一個空對象(C.64),它可能引起誤解甚至危險。因此我們努力避免移動左值(它們可能在后續(xù)代碼中被使用)。

Notes(注意)

如果源數(shù)據(jù)是右值,移動操作會隱式進(jìn)行(例如return處理或函數(shù)的返回值),在這種情況下進(jìn)行顯式移動操作,會導(dǎo)致代碼被漫無目標(biāo)地的復(fù)雜化。相反,編寫帶返回值的簡短函數(shù),這樣無論是函數(shù)的返回值還是調(diào)用側(cè)的接受動作都可以很自然地被優(yōu)化。

通常情況下,遵循本文檔中的準(zhǔn)則(包括不要不必要地擴(kuò)大變量作用域,編寫帶返回值的簡短函數(shù),返回局部變量等)可以幫助消除顯式執(zhí)行std::move的大部分需求。

在顯式移動一個對象到另外的作用域時,顯式移動是有必要的。特別是:

1.將對象傳遞給一個“下沉”函數(shù)時(接管變量所有權(quán)的函數(shù),譯者注)

2.實現(xiàn)對象自身移動操作(移動構(gòu)造函數(shù),移動賦值運算符)和交換操作時

Example, bad(反面示例)

void sink(X&& x);   // sink takes ownership of x

void user()
{
   X x;
   // error: cannot bind an lvalue to a rvalue reference
   sink(x);
   // OK: sink takes the contents of x, x must now be assumed to be empty
   sink(std::move(x));

   // ...

   // probably a mistake
   use(x);
}

通常情況下,std::move()作為為&&參數(shù)提供實參。而且在移動之后,應(yīng)該認(rèn)為對象已經(jīng)被移走(參見C.64)并且在賦予新值之前不要獲取對象的狀態(tài)。

void f() {
   string s1 = "supercalifragilisticexpialidocious";

   string s2 = s1;             // ok, takes a copy
   assert(s1 == "supercalifragilisticexpialidocious");  // ok

   // bad, if you want to keep using s1's value
   string s3 = move(s1);

   // bad, assert will likely fail, s1 likely changed
   assert(s1 == "supercalifragilisticexpialidocious");
}
Example(示例)
void sink(unique_ptr<widget> p);  // pass ownership of p to sink()

void f() {
   auto w = make_unique<widget>();
   // ...
   sink(std::move(w));               // ok, give to sink()
   // ...
   sink(w);    // Error: unique_ptr is carefully designed so that you cannot copy it
}
Notes(注意)

std::move()實際上是目標(biāo)為&&的類型轉(zhuǎn)換;它自己不會移動任何東西,而是將命名對象標(biāo)記為一個移出操作的候選者。語言已經(jīng)知道對象可以被移出的一般情況,特別是函數(shù)的返回值,因此不要因為多余的std::move導(dǎo)致代碼復(fù)雜化。

永遠(yuǎn)不要只是因為聽說它更高效就使用std::move。通常不要相信那些脫離具體數(shù)據(jù)的所謂“高效”。通常不要沒有理由地讓代碼復(fù)雜化。永遠(yuǎn)不要對常量對象調(diào)用std::move(),這會不知不覺地產(chǎn)生一個拷貝。

Example, bad(反面示例)

vector<int> make_vector() {
   vector<int> result;
   // ... load result with data
   return std::move(result);       // bad; just write "return result;"
}

永遠(yuǎn)不要返回局部變量的移動結(jié)果;因為語言已經(jīng)知道這個變量可以作為移動操作的候選,在這種代碼中增加move代碼不但沒有任何幫助,而且對于某些編譯器,由于產(chǎn)生了額外的指向局部變量的引用,增加move代碼會影響RVO(返回值優(yōu)化)的正常執(zhí)行。

Example, bad(反面示例)

vector<int> v = std::move(make_vector());   // bad; the std::move is entirely redundant

如果函數(shù)f以傳值方式返回結(jié)果,永遠(yuǎn)不要對這個返回值調(diào)用move操作,例如X=move(f());語言已經(jīng)知道返回值是臨時變量并且可以進(jìn)行移出操作。

Example(示例)

void mover(X&& x) {
   call_something(std::move(x));         // ok
   call_something(std::forward<X>(x));   // bad, don't std::forward an rvalue reference
   call_something(x);                    // suspicious, why not std::move?
}

template<class T>
void forwarder(T&& t) {
   call_something(std::move(t));         // bad, don't std::move a forwarding reference
   call_something(std::forward<T>(t));   // ok
   call_something(t);                    // suspicious, why not std::forward?
}
Enforcement(實施建議)
  • 標(biāo)記針對右值或者已經(jīng)被語言看作是右值的對象調(diào)用std::move的情況。包括std::move(local_variable);,std::move(f()),這里函數(shù)f是一個以傳值方式返回結(jié)果的函數(shù)。

  • 標(biāo)記沒有用于處理左值的const S&型重載函數(shù),只有一個處理右值(參數(shù)類型:S&&)的函數(shù)的情況。

  • 標(biāo)記向參數(shù)傳遞std::move執(zhí)行結(jié)果的情況,除非參數(shù)類型是右值引用類型X&&,或者參數(shù)類型為只移動不拷貝類型并且以傳值方式傳遞。

  • 標(biāo)記對轉(zhuǎn)交引用類型調(diào)用std::move的情況(T&&,這里T是模板參數(shù))。

  • 標(biāo)記std::move運用于指向非常變量的右值引用以外的情況。(前面規(guī)則的更普遍形式,以包含非轉(zhuǎn)交參數(shù)的情況)

  • 標(biāo)記std::forward用于右值引用的情況(X&&,這里X是具體類型),轉(zhuǎn)而使用std::move。

  • 標(biāo)記std::forward用于轉(zhuǎn)交引用之外的情況。(前面規(guī)則的更普遍形式,它可以覆蓋非移動參數(shù)的情況。)

  • 標(biāo)記對象可能被執(zhí)行移出操作而且下一個是常量操作(讀取對象值,譯者注)的情況;哪里應(yīng)該首先有一個非常量操作(以便修改對象值,譯者注),最好是重新設(shè)置對象值的賦值操作。

    感謝各位的閱讀,以上就是“C++中什么時候使用std::move”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對C++中什么時候使用std::move這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

    本文題目:C++中什么時候使用std::move?
    文章來源:http://muchs.cn/article40/jehpeo.html

    成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、外貿(mào)網(wǎng)站建設(shè)、網(wǎng)站改版、App開發(fā)虛擬主機(jī)、微信小程序

    廣告

    聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

    外貿(mào)網(wǎng)站制作