std::move操作是否会确保容器销毁其现有对象?
关于std::vector移动赋值时元素销毁时机的问题
问题代码
#include <iostream> #include <vector> class A { public: A(const A&) = default; A(A&&) = default; A& operator=(const A&) = default; A& operator=(A&&) = default; A() = default; ~A() { std::cout << "~A()\n"; } }; int main() { std::vector<A> v1; std::vector<A> v2; v1.emplace_back(); v1 = std::move(v2); std::cout << "moved\n"; }
当前观察到的输出:
~A() moved
疑问:能否依赖std::move来销毁v1中的元素?上述输出是否确定?是否可能出现如下输出:
moved ~A()
解答
首先明确:你不能依赖移动赋值操作立刻销毁原容器中的元素,两种输出都是符合标准的合法情况。
根据C++标准,std::vector的移动赋值运算符需要满足:
- 移动完成后,原容器(此处为
v2)处于合法但未指定的状态(可安全销毁、赋值或调用无参数成员函数如clear()) - 被赋值的容器
v1会接管v2的内部资源,但标准并未强制要求必须在移动赋值过程中立刻销毁自身原有的元素,具体销毁时机由容器的实现决定。
你提到的用std::swap实现移动赋值是完全合法的:这种实现下,v1原来的元素会被转移到一个临时对象中,临时对象的销毁会延迟到当前作用域的末尾(比如main函数里std::cout << "moved\n";执行之后),这就会出现moved先输出、随后才打印~A()的情况。
另一种常见实现逻辑是先销毁v1自身的元素,再接管v2的资源,这种情况下就会先输出~A(),再打印moved。
所以结论是:移动赋值操作中原有元素的销毁时机是未指定的,不能依赖它在移动赋值完成前执行。如果需要确保元素立刻被销毁,建议显式调用v1.clear()后再进行移动赋值,或者通过其他方式严格控制对象生命周期。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

