《Effective Modern C++》学习笔记之条款二十九:假定移动操作不存在/成本高/未使用

我们知道,C++98标准库都已经为C++11彻底翻修过,目的是为那些移动比复制更快的型别添加移动操作,但是如果你现有的代码没有为C++11做过专门修改,那性能也不会有很大提升,因为虽然说C++11原因为那些缺少移动操作的类生成移动操作,但有个前提条件,即该类未声明复制操作、移动操作以及析构函数;而且类中的数据成员或者父类禁用了移动,这也将导致编译期生成的移动操作被抑制掉。

另外,有些类的移动可能并不会比复制快多少,例如 std::array这个新容器类别,它实质上就是带有STL接口的内建数组,这一点和其他容器有很大区别,其他容器都是将其内容存放在堆上,然后维护一个堆指针,当需要移动时,只需要将指针重新赋值即可,但std::array的元素是直接存储在容器内,所以无论是复制还是移动,其复杂度都和std::array元素个数成正比,因为容器中的每个元素都必须逐一复制或移动,所以速度上可能不会有很大提升。

除了std::array外,还有一个我们常见类std::string,因为许多std::string都采用了小型字符串优化(SSO),采用了SSO后,小型字符串(一般是指容量不超过15个字符)会将内存存储在对象的某个缓冲区内,而非堆上,和std::array一样,当小型字符串发生移动或者复制时,需要将其元素逐一复制或移动,而非直接修改堆指针,所以它的移动也并不会比复制快多少。

总而言之,在以下几个场景下,C++11的移动语义并不会给你带来什么好处:

  • 没有移动操作:待移动的对象没有提供移动操作,因此移动请求就变成了复制请求
  • 移动未能更快:待移动的对象虽然有移动操作,但是并不一定比复制快
  • 移动不可用:移动本可以发生的语境下,要求移动操作不可以发生异常,但是该操作未加上noexcept声明
  • 源对象是个左值:除极少数特例外,只有右值可以作为移动操作的源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Chiang木

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值