C++ primer学习笔记-13章-移动构造函数和移动赋值重载函数

移动构造函数

移动构造函数为什么需要加noexcept

必须在类头文件的声明中和定义中(如果定义在类外的话)都指定noexcept

noexcept关键字修饰的函数不会在执行过程中抛出异常。如果标记为noexcept的函数抛出异常,那么编译器会调用std::terminate()函数中断程序执行。

1.void func() noexcept;
2.为noexcept额外提供一个常量表达式作为其参数,true函数被标记为不抛出异常
constexpr bool suppressExcept = true;
void fun() noexcept (suppressExcept);
C++11类结构隐式自动声明的和程序员主动声明的不带任何修饰符的函数都是默认noexcept(true)的

移动构造函数可以在对象进行赋值的时候直接移动原对象已经分配好的资源,从而省去重新分配内存再拷贝的过程。STL中多数容器resizing的时候调用容器元素的移动构造函数来移动资源。

_VSTD::move_if_noexcept()

为了保证容器类型数据的安全,多数情况下指挥调用被标记为noexcept的移动构造函数,否则会调用拷贝构造函数。因为,资源的移动过程中如果抛出异常,那么正在被处理的原始对象数据可能会因为异常而丢失,如果是拷贝构造函数,对资源进行拷贝而不对原始数据进行更改,无论是否抛出异常,都不会影响数据的正确性。

移动赋值重载函数

移动赋值重载函数也需要加上noexcept
移动赋值重载函数必须正确处理自赋值。

移后源对象必须可析构

值得注意的是,从一个给定对象移动数据并不会销毁此对象,但必须保证,经过”移动”操作后,源对象是可以被安全销毁的,也就是当编写一个移动操作后,必须保证移后源对象进入一个可析构的状态。
为了满足这一要求,我们通过将移后源对象的指针置为 nullptr 来实现。

在移动之后,移后源对象必须保持有效的(还是可以执行对象中的所有操作)、可析构的,但是用户不能对其值进行假设。

默认移动构造函数

与拷贝构造函数不同的是,只有当类没有定义拷贝构造函数、拷贝赋值运算符、析构函数且类的每个非 static 数据都可移动时,编译器才会为它合成移动构造函数或移动赋值表达式。编译器可以移动内置类型的成员,如果一个成员是类类型,且该类有对应的移动操作,编译器也能移动这个成员。

和拷贝操作不同,移动操作永远不会隐式定义为删除的函数;

合成的移动操作定义为删除的函数遵循定义删除的合成拷贝类似原则:

  1. (和拷贝构造函数不同)移动构造函数被定义为删除的函数的条件:有类成员定义了自己的拷贝构造函数并且未定义移动构造函数,或者又是有类成员未定义自己的拷贝构造函数并且编译器不能为其合成移动构造函数;
  2. 如果有类成员的移动构造函数或移动赋值运算符被定义为删除的或是不可访问的,则类的移动构造函数或移动赋值运算符被定义为删除的;
  3. (和拷贝构造函数类似)如果类的析构函数被定义为删除的或是不可访问的,则类的移动构造函数被定义为删除的;
  4. (和拷贝赋值运算符类似)如果类成员是const的或者是引用,则类的移动赋值运算符被定义为删除的;

移动操作和拷贝操作的关联

如果定义了拷贝构造函数或移动赋值运算符,则该类合成拷贝构造函数和拷贝构造赋值运算符会被定义为删除。

移动右值,拷贝左值…

如果没有移动构造函数,右值也被拷贝。(可以将 T&& 转换为const T &)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值