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

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

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

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

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

假设的适用边界与例外

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

结论

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

原著在线阅读地址

相关推荐
Jasmine_llq4 小时前
《B4356 [GESP202506 二级] 数三角形》
开发语言·c++·双重循环枚举算法·顺序输入输出算法·去重枚举算法·整除判断算法·计数统计算法
山栀shanzhi4 小时前
在做直播时,I帧的间隔(GOP)一般是多少?
网络·c++·面试·ffmpeg
王老师青少年编程5 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【排序贪心】:魔法
c++·算法·贪心·csp·信奥赛·排序贪心·魔法
晓觉儿5 小时前
【GPLT】2026年第十一届团队程序设计天梯赛赛后题解(已写2h,存档中)
数据结构·c++·算法·深度优先·图论
6Hzlia5 小时前
【Hot 100 刷题计划】 LeetCode 394. 字符串解码 | C++ 单栈回压法
c++·算法·leetcode
流年如夢6 小时前
自定义类型进阶:联合与枚举
java·c语言·开发语言·数据结构·数据库·c++·算法
Little At Air6 小时前
C++stack模拟实现
linux·开发语言·c++·算法
rayyy96 小时前
c++, sizeof(string)和string.size()有什么区别
c++
郭涤生7 小时前
C++ 回调较容易出错问题
开发语言·c++
yi.Ist7 小时前
2025CCPC郑州邀请赛
c++·学习·算法·acm