You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何隐式移动构造函数将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 00:35:25