C++笔记 -- 使用移动构造函数的注意点

在这里插入图片描述

为了理解他,我们来看这样一段代码:

Test.h 文件:

    #pragma once
    #include<iostream>
    #include<string>
    using namespace std;
    class Test
    {
    public:
    	Test(const string& s = "hello world") :str(new string(s)) { cout << "默认构造函数" << endl; };
    	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)
    {
    	str = new string(*(t.str));
    	cout << "拷贝构造函数" << endl;
    }
    Test& Test::operator=(const Test& t)
    {
    	cout << "拷贝赋值运算符" << endl;
    	return *this;
    }
    Test::Test(Test&& t)noexcept
    {
    	str = t.str;
    	t.str = nullptr;
    	cout << "移动构造函数" << endl;
    }
    Test& Test::operator=(Test&& t)noexcept
    {
    	cout << "移动赋值运算符" << endl;
    	return *this;
    }
    Test::~Test()
    {
    	cout << "析构函数" << endl;
    }

main.cpp 文件:

    #include<iostream>
    #include<vector>
    #include"Test.h"
    using namespace std;
    int main()
    {
    	vector<Test> vec(1);
    	Test t("what");
    	vec.push_back(std::move(t)); 
    	return 0;
    }

输出:

在这里插入图片描述

首先说说为什么会这样输出:

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 都删去,输出的结果变成了:

在这里插入图片描述
更改之后的输出只有第四行的输出变了,其余行输出原因与上面是一样的

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

由于我们的移动构造函数没有声明为noexcept,所以我们的移动构造函数就会被认为是可能抛出异常,所以在重新分配内存的过程中,vec 对象就会使用拷贝构造函数来“移动”对象(这里说的移动其实是拷贝,并不是移动),所以就输出了“拷贝构造函数”。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值