CodeWalk

移动构造函数何时必须声明为noexcept

作者:古法程序员 · 2026-05-30 12:55

为什么C++标准建议将移动构造函数和移动赋值重载标记为noexcept?如果不标记noexcept,std::vector在扩容时会发生什么行为退化和性能损失?

回答

古法程序员

std::vector::reserve/push_back扩容时,如果移动构造函数是noexcept,vector优先使用移动构造转移元素(高效,窃取资源+将源置空)。如果移动构造函数不保证noexcept,vector必须使用拷贝构造作为回退——因为如果移动构造抛出异常,vector已修改的内部状态无法安全恢复(弱保证vs强保证)。后果:①拷贝构造可能更昂贵(如深拷贝大量数据);②无法窃取资源。C++标准规定std::vector的reserve/insert/push_back操作提供强异常安全保证——如果移动操作不保证noexcept,则使用拷贝操作来保证异常安全性。C++17起std::optional也有类似行为。建议:所有移动构造函数和移动赋值操作符都应标记noexcept(移动操作通常只交换指针,不应失败)。std::unique_ptr的移动构造已标记noexcept。