【Effective Modern C++】第五章:右值引用、移动语义和完美转发:29. 认识移动操作的缺点

移动语义是 C++11 最核心的特性之一:它能在满足特定条件时,用低开销的移动操作替代高开销的复制操作,甚至能让 C++98 的代码重新编译后直接获得性能提升。但也正因如此,移动语义的效果和适用范围被普遍夸大,本条款的目的是让开发者理性看待移动语义,避免过度乐观。

移动语义无优势 / 失效的核心场景

移动语义无法带来性能提升、甚至直接退化为复制操作的四类典型场景:

  • 类型本身不支持移动操作:对于 C++98 遗留的未适配类型、不符合编译器默认生成移动操作条件的自定义类型(如声明了复制操作、移动操作或析构函数,或成员 / 基类禁用了移动),移动写法会直接退化为复制,无法带来任何性能提升。
  • 移动操作并不比复制更快:并非所有支持移动的类型都有低开销的实现。比如 std::array,数据直接存储在对象本身而非堆内存,移动需要线性时间逐个处理元素,开销与复制处于同一量级;再比如开启了小字符串优化(SSO)的短 std::string,数据存储在对象内部缓冲区,移动开销与复制几乎无差异。
  • 移动操作被上下文强制禁用 :标准库部分容器操作要求强异常安全保证,若移动操作未声明noexcept,即便有更高效的移动实现,编译器也会强制使用复制操作,避免移动抛异常破坏原有安全约定。
  • 源对象无法触发移动:除极少数例外场景,只有右值能作为移动操作的来源,左值对象无法触发移动,只能执行复制。

假设的适用边界与例外

  • 该保守假设的核心适用场景,是通用模板代码 (无法预知待处理类型是否支持高效移动)、频繁修改的不稳定代码(类型特性可能随时变动),这类场景需要像 C++98 时代一样,保守地处理对象复制。
  • 若开发者明确知晓代码所用类型支持高效移动操作,且调用上下文能合法触发移动,就无需遵循该保守假设,可安全使用移动语义替代复制。

结论

  1. 通用代码场景下,假定移动操作不存在、成本高、未被使用;
  2. 在已知类型特性、明确支持高效移动语义的代码中,无需遵循上述保守假设。

原著在线阅读地址

相关推荐
化学在逃硬闯CS2 小时前
【Leetcode热题100】108.将有序数组转换为二叉搜索树
数据结构·c++·算法·leetcode
tankeven2 小时前
HJ86 求最大连续bit数
c++·算法
写代码的小球3 小时前
C++ 标准库 <numbers>
开发语言·c++·算法
拳里剑气3 小时前
C++:哈希
开发语言·数据结构·c++·算法·哈希算法·学习方法
闻缺陷则喜何志丹3 小时前
【高等数学】导数与微分
c++·线性代数·算法·矩阵·概率论
智者知已应修善业3 小时前
【项目配置时间选择自己还是团体】2025-3-31
c语言·c++·经验分享·笔记·算法
闻缺陷则喜何志丹3 小时前
【分组背包】P12316 [蓝桥杯 2024 国 C] 循环位运算|普及+
c++·算法·蓝桥杯·洛谷·分组背包
BOTTLE_平3 小时前
C++图论全面解析:从基础概念到算法实践
c++·算法·图论
Lenyiin3 小时前
《 C++ 修炼全景指南:二十四 》彻底攻克图论!轻松解锁最短路径、生成树与高效图算法
c++·算法·图论·邻接表·邻接矩阵·最小生成树·最短路径