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

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

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

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

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

假设的适用边界与例外

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

结论

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

原著在线阅读地址

相关推荐
揽星河..1 小时前
【C语言】分支和循环
c语言·c++·算法
Fuyo_11192 小时前
C++ AVL树保姆级详解:从平衡因子到四大旋转机制
java·c++·算法
傲世仙尊3 小时前
继承-类设计层次复用切片转换与菱形继承的死结
c++
架构师伯子明4 小时前
FFmpeg C++学习(一):编译和demo
开发语言·c++·学习
纪念 2294 小时前
C++算法(六)
开发语言·c++·算法
ShineWinsu4 小时前
对于Qt:QCheckBox常见属性的详细解析
c++·qt·面试·笔试·gui·qcheckbox·多选框
AI的探索之旅5 小时前
97 个 OpenCV 实例(三十七):二维码识别,一张图四个码的陷阱
c++·opencv·计算机视觉
UIU1145 小时前
P16237 [蓝桥杯 2026 省 B] 应急布线
数据结构·c++·算法·蓝桥杯
raindayinrain5 小时前
c++设计模式
开发语言·c++·设计模式
旖旎夜光6 小时前
LeetCode 315: 算右侧小于当前元素的个数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法