C 筆記 使用移動建構函式的注意點

2021-09-11 15:15:29 字數 1698 閱讀 2074

為了理解他,我們來看這樣一段**:

test.h 檔案:

#pragma once

#include#includeusing namespace std;

class test

;test(const test& t);

test& operator=(const test& t);

test(test&& t)noexcept;

test& operator=(test&& t)noexcept;

~test();

public:

string * str;

};

test.cpp 檔案

#include"test.h"

test::test(const test& t)

test& test::operator=(const test& t)

test::test(test&& t)noexcept

test& test::operator=(test&& t)noexcept

test::~test()

main.cpp 檔案:

#include#include#include"test.h"

using namespace std;

int main()

輸出:

首先說說為什麼會這樣輸出:

1、第乙個 「預設建構函式」 是因為vector vec(1) , 所以事先使用預設建構函式構造了乙個test物件

2、第二個 「預設建構函式」 是因為test t ,使用預設建構函式構造了乙個物件

3、第三個 「移動建構函式」 大多數人會以為是 vec.push_back(std::move(t)) ,push_back 導致物件的移動而輸出的。具體的原因其實是由於重新分配記憶體而導致的,我們的 vector 物件 vec 初始的容量只有 1 ,且裡面已經有乙個物件了,就是vector vec(1)的時候建立的,所以再向vec裡面新增test物件時,就會導致vec重新分配記憶體。由於vec中的物件定義了移動建構函式且是可用的(因為我們將其宣告為了noexcept),所以就會呼叫移動建構函式將vec中原始的那個物件移動到新的記憶體中,從而輸出 「移動建構函式」。

4、第四個 「移動建構函式」 才是因為test 物件 t 被移動到vector 物件 vec 新的空間而輸出的

5、第五個 「析構函式」 是因為重新分配記憶體後,原來的記憶體將被銷毀,所以輸出乙個「析構函式」

6、後面三個 「析構函式」 是因為執行了return 0, 記憶體被釋放,vec 和 t 都被析構,所以輸出三個 「析構函式」

將 test.h 和 test.cpp 檔案中的noexcept 都刪去,輸出的結果變成了:

更改之後的輸出只有第四行的輸出變了,其餘行輸出原因與上面是一樣的

第四行的輸出由 「移動建構函式」 變成了 「拷貝建構函式」 ,原因是:

C 移動建構函式和拷貝建構函式

我們用物件 a初始化物件b 後物件 a我們就不在使用 了,但是物件a的空間還在呀 在析構之前 既然拷貝建構函式,實際上就是把a物件的內容複製乙份到b中,那麼為什麼我們不能直接使用a的空間呢?這樣就避免了新的空間的分配,大大降低了 構造的成本 這就是移動建構函式設計的初衷 拷貝建構函式 中,對於指標,...

c 移動建構函式淺解

本部落格是 c 新經典 王健偉著 的學習筆記,本人是c 初學者,如果有理解錯誤或者理解不足的地方,還請大神能夠指正。c 搞出了std move把左值轉成右值,還搞出移動建構函式,藉此改善效能問題,個人感覺,對我這樣的初學者帶來一定的理解難度。我總結了一下,所謂拷貝建構函式在標準上,是深拷貝,為了改善...

構造析構拷貝函式注意點

1 構造析構拷貝函式都沒有返回值 2 建構函式可以過載 3 析構函式沒有形參 4 手動呼叫析構函式後程式還會再次呼叫,確保呼叫兩次不會影響程式 5 拷貝建構函式的初始化形式 define crt secure no warnings include class test test int x,int...