移动构造函数

 

 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 }

运行结果:
ios

首先说说为何会这样输出:函数

一、第一个 “默认构造函数” 是由于vector<Test> vec(1) , 因此事先使用默认构造函数构造了一个Test对象this

二、第二个 “默认构造函数” 是由于Test t ,使用默认构造函数构造了一个对象spa

三、第三个 “移动构造函数” 大多数人会觉得是 vec.push_back(std::move(t)) ,push_back 致使对象的移动而输出的。具体的缘由实际上是因为从新分配内存而致使的,咱们的 vector 对象 vec 初始的容量只有 1 ,且里面已经有一个对象了,就是vector<Test> vec(1)的时候建立的,因此再向vec里面添加Test对象时,就会致使vec从新分配内存。因为vec中的对象定义了移动构造函数且是可用的(由于咱们将其声明为了noexcept),因此就会调用移动构造函数将vec中原始的那个对象移动到新的内存中,从而输出 “移动构造函数”。.net

四、第四个 “移动构造函数” 才是由于Test 对象 t 被移动到vector 对象 vec 新的空间而输出的3d

五、第五个 “析构函数” 是由于从新分配内存后,原来的内存将被销毁,因此输出一个“析构函数”code

六、后面三个 “析构函数” 是由于执行了return 0, 内存被释放,vec 和 t 都被析构,因此输出三个 “析构函数”对象

将 Test.h 和 Test.cpp 文件中的noexcept 都删去,输出的结果变成了:blog

更改以后的输出只有第四行的输出变了,其他行输出缘由与上面是同样的内存

第四行的输出由 “移动构造函数” 变成了 “拷贝构造函数” ,缘由是:

因为咱们的移动构造函数没有声明为noexcept,因此咱们的移动构造函数就会被认为是可能抛出异常,因此在从新分配内存的过程当中,vec 对象就会使用拷贝构造函数来“移动”对象(这里说的移动实际上是拷贝,并非移动),因此就输出了“拷贝构造函数”。

参考资料

1. C++笔记之移动构造函数什么时候会被调用,什么时候不会被调用

相关文章
相关标签/搜索