C++存在移动构造且操作右值时仍调用拷贝构造的原因
问题1解答
std::vector扩容时需要满足强异常安全保证:如果扩容过程中出现异常,原有容器内的元素必须保持完整不被损坏。
你自定义的移动构造函数没有标记为noexcept,STL默认会认为该移动构造存在抛出异常的风险。如果此时调用移动构造迁移旧元素,一旦移动过程抛出异常,已经被移动的旧元素就处于失效状态,无法回滚到扩容前的状态,违反异常安全要求。所以vector会fallback到拷贝构造函数,对旧的存储10的对象执行深拷贝,保证原有元素不会被修改。
问题2解答
数值为20的对象是你刚构造的临时右值,属于本次push_back要插入的新元素,不需要参与旧空间已有元素的迁移流程。它只需要直接调用移动构造放到扩容后的新空间对应位置即可,不需要做深拷贝。
修复方案
只需要给移动构造加上noexcept声明,告诉STL该移动构造不会抛出异常,vector扩容时就会优先调用移动构造迁移旧元素,避免深拷贝:
Move(Move&& source) noexcept : data{ source.data } { cout << "Move Constructor for " << *source.data << endl; source.data = nullptr; }
内容的提问来源于stack exchange,提问作者LearningNoob123
相关产品推荐
相关产品推荐

