移動構造函數


 

 1 #include<iostream>
 2 #include<vector>
 3 #include<string>  
 4 using namespace std;
 5 
 6 class Test
 7 {
 8 public:
 9     Test(const string& s = "hello world") :str(new string(s)) { cout << "默認構造函數" << endl; };
10     Test(const Test& t);
11     Test& operator=(const Test& t);
12     Test(Test&& t) noexcept;
13     Test& operator=(Test&& t) noexcept;
14     ~Test();
15 public:
16     string * str;
17 };
18 
19 Test::Test(const Test& t)
20 {
21     str = new string(*(t.str));
22     cout << "拷貝構造函數" << endl;
23 }
24 Test& Test::operator=(const Test& t)
25 {
26     cout << "拷貝賦值運算符" << endl;
27     return *this;
28 }
29 Test::Test(Test&& t)noexcept
30 {
31     str = t.str;
32     t.str = nullptr;
33     cout << "移動構造函數" << endl;
34 }
35 Test& Test::operator=(Test&& t)noexcept
36 {
37     cout << "移動賦值運算符" << endl;
38     return *this;
39 }
40 Test::~Test()
41 {
42     cout << "析構函數" << endl;
43 }
44 
45 int main()
46 {
47     vector<Test> vec(1);
48     Test t("what");
49     vec.push_back(std::move(t));
50     return 0;
51 }

運行結果:

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

1、第一個 “默認構造函數” 是因為vector<Test> vec(1) , 所以事先使用默認構造函數構造了一個Test對象

2、第二個 “默認構造函數” 是因為Test t ,使用默認構造函數構造了一個對象

3、第三個 “移動構造函數” 大多數人會以為是 vec.push_back(std::move(t)) ,push_back 導致對象的移動而輸出的。具體的原因其實是由於重新分配內存而導致的,我們的 vector 對象 vec 初始的容量只有 1 ,且里面已經有一個對象了,就是vector<Test> vec(1)的時候創建的,所以再向vec里面添加Test對象時,就會導致vec重新分配內存。由於vec中的對象定義了移動構造函數且是可用的(因為我們將其聲明為了noexcept),所以就會調用移動構造函數將vec中原始的那個對象移動到新的內存中,從而輸出 “移動構造函數”。

4、第四個 “移動構造函數” 才是因為Test 對象 t 被移動到vector 對象 vec 新的空間而輸出的

5、第五個 “析構函數” 是因為重新分配內存后,原來的內存將被銷毀,所以輸出一個“析構函數”

6、后面三個 “析構函數” 是因為執行了return 0, 內存被釋放,vec 和 t 都被析構,所以輸出三個 “析構函數”

將 Test.h 和 Test.cpp 文件中的noexcept 都刪去,輸出的結果變成了:

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

第四行的輸出由 “移動構造函數” 變成了 “拷貝構造函數” ,原因是:

由於我們的移動構造函數沒有聲明為noexcept,所以我們的移動構造函數就會被認為是可能拋出異常,所以在重新分配內存的過程中,vec 對象就會使用拷貝構造函數來“移動”對象(這里說的移動其實是拷貝,並不是移動),所以就輸出了“拷貝構造函數”。

參考資料

1. C++筆記之移動構造函數何時會被調用,何時不會被調用


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM