为何隐式移动构造函数将obj1数据移至obj2后未使其处于空白或不确定状态?
为什么隐式移动构造后原对象的内置类型值未改变?
你预期编译器生成的隐式移动构造函数会把obj1的val“移走”,让obj1处于空白或值为0的状态,但实际输出中obj1.val仍为3,核心原因是C++对内置类型的移动操作本质就是复制。
隐式移动构造函数的行为规则
编译器自动生成的隐式移动构造函数,会根据成员变量的类型做不同处理:
- 对于具备移动语义的类型(如
std::unique_ptr、std::string):会调用它们的移动构造函数,转移资源所有权,原对象进入「有效但未定义」的状态(通常资源被清空); - 对于内置类型(int、bool、基础指针等):不存在真正的“移动”逻辑,编译器直接复制其数值,原对象的数值不会被修改。
结合你的代码分析
你的Demo类中val是int类型,属于内置类型。执行Demo obj2(std::move(obj1))时,隐式移动构造函数只是把obj1.val的3复制给obj2.val,obj1.val本身没有任何修改,所以移动后输出的obj1.val依然是3。
实现预期效果的方法
如果希望移动后原对象的val被置为0,需要显式定义移动构造函数:
#include <iostream> #include <utility> // 用于std::exchange using namespace std; class Demo { public: int val = 3; // 显式移动构造函数:转移val的同时将原对象val置为0 Demo(Demo&& other) noexcept : val(std::exchange(other.val, 0)) {} // 需显式保留默认构造函数(因为定义了移动构造,默认构造不会自动生成) Demo() = default; }; int main() { Demo obj1; cout << "before move obj1.val :" << obj1.val << std::endl; Demo obj2(std::move(obj1)); cout << "after move obj1.val :" << obj1.val << std::endl; cout << "after move obj2.val :" << obj2.val << std::endl; return 0; }
此时输出会符合你的预期:
before move obj1.val :3 after move obj1.val :0 after move obj2.val :3
补充说明
C++标准仅要求移动操作后原对象处于有效但未定义的状态——你可以对原对象赋值,但不能依赖它移动后的原有值。编译器对内置类型采用复制而非修改的行为,完全符合标准规定。
内容的提问来源于stack exchange,提问作者Mangy
相关产品推荐
相关产品推荐

