關於C 11的Move建構函式和棧上的區域性物件

2021-08-14 08:13:42 字數 2326 閱讀 8272

關於c++11的move建構函式和棧上的區域性物件

看乙個測試例子:

呼叫gettestmovefromstack會先在棧上建立乙個區域性變數。

當其return以後傳遞值給外部的tt物件時,會首先呼叫move 建構函式。(說明由函式返回的棧上區域性變數被當做右值處理了)

其後棧上的物件會被銷毀。

外部tt物件的data資料值是10.

接著外部的tt物件在使用完畢以後也會被銷毀。

二,將gettestmovefromstack函式稍作修改,

testmove & gettestmovefromstack() ;

return test;

}

這時候可以看到:棧上的物件會先被呼叫析構函式。接著外層物件tt的拷貝建構函式被呼叫(全程不會呼叫move建構函式)

可是tt物件的拷貝建構函式被呼叫的時候記憶體棧物件由於已經被銷毀,這時候是乙個非法的資料訪問(由於只是讀取int值沒有造成記憶體訪問錯誤)

呼叫關係:

可以看到外層tt物件的值已經出錯了。

三,第三種寫法引用返回區域性棧物件,外部採用棧物件接受資料。

testmove & gettestmovefromstack() ;

return test;

}

testmove & tt = gettestmovefromstack();
外部採用引用方式來接收資料,這樣外部的tt不會呼叫任何建構函式。而且只要棧不被破壞似乎**還能正常執行,不會報錯。

可以看到棧物件確實被銷毀了,但是棧資料沒被覆蓋所以一些基本操作還能執行。

寫乙個覆蓋棧空間的函式試試,果然報錯了。

總結:如果要把棧上的區域性物件返回給外部,語法上應該直接使用copy-by-value的方式返回,不應該使用引用返回。

這樣copy-by-value返回乙個棧上的臨時物件會被當做右值處理,然後外界接受函式返回值時,會呼叫move建構函式。

如果採用顯式的reference的方式返回,一定不能是棧上建立的物件(不會被當做右值處理,並且在return以前會先被銷毀)

另外界如果才用引用方式接受函式返回值,其值的**也不應該是棧上建立的物件(而且這種錯誤還不會導致程式馬上掛,會引發奇怪的問題)

如果乙個物件被使用std::move操作轉換為右值以後,作為assignment 或者constructor引數傳給別的物件進行move構造(尤其是後者),如果該物件使用default的move建構函式,那麼等move所使用的語句結束以後不應該繼續使用被move過的物件,因為這可能是很危險的。

例如有乙個class a

接著 a a;

a b = std::move(a);

接著不應該繼續再使用a

不過推薦處於安全考慮如果類會被std::move轉換為右值的情況下, 應該給該類寫明move 建構函式。防止出問題

C 11 繼承建構函式和委託建構函式

如果基類的建構函式很多,那麼子類的建構函式想要實現同樣多的構造介面必須一一呼叫基類的建構函式,於是c 11 引入繼承建構函式。class a a double indouble,int inint a float infloat,int inint,const char char class b p...

C 11 移動建構函式

移動建構函式是什麼?先舉個例子,你有一本書,你不想看,但我很想看,那麼我有哪些方法可以讓我能看這本書?有兩種做法,一種是你直接把書交給我,另一種是我去買一些稿紙來,然後照著你這本書一字一句抄到稿紙上。顯然,第二種方法很浪費時間,但這正是有些深拷貝建構函式的做法,而移動建構函式便能像第一種做法一樣省時...

C 11 委派建構函式

一 委派建構函式 深入理解c 11 委派構造 就是指委派函式將構造的任務派給了目標建構函式來完成這樣一種類構造的方式。c 11中的委派建構函式是在建構函式的初始化列表位置進行構造的 委派的 基準版本 的建構函式稱為目標建構函式,呼叫 基準版本 的建構函式稱為委派建構函式 舉例 namespace d...