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

std::move操作后被移动对象仍可访问的原因探究——以C++代码中d1.a的访问为例

为什么std::move后源对象依然能正常访问?

先把你的代码格式化好方便查看:

struct Base { 
    Base(int a_) : a(a_) { } 
    int a; 
}; 

class Derived: public Base { 
public: 
    Derived(int i): Base(i) { } 
    Derived(const Derived && rhs) : Base(std::move(rhs)) { } 
}; 

int main() { 
    Derived d1(2); 
    Derived d2 = std::move(d1); 
    std::cout << d1.a << '\n'; 
}

你的疑问核心其实是对std::move和移动语义的误解,我来拆解清楚:

  • std::move根本不是“窃取资源”的操作:它只是个编译期类型转换工具,把左值(比如d1)转换成右值引用类型,目的是让后续的构造/赋值操作能匹配到移动版本的函数。它本身不会修改源对象的任何状态,更不会“搬走”什么东西。

  • 真正的移动行为由移动构造函数决定:
    你的Derived移动构造函数调用了Base(std::move(rhs)),但Base没有自定义移动构造函数,编译器会自动生成一个默认的移动构造。对于int这种内置类型,默认移动构造的逻辑和拷贝构造完全一样——就是把值复制给新对象,源对象的a值不会有任何变化。所以d1.a还是2,自然能正常输出。

  • 什么时候源对象状态会改变?
    只有当移动构造函数里显式地对源对象的资源进行了转移时,源对象才会进入“有效但未定义”的状态。比如如果Base里有个std::string或者std::vector,默认移动构造会把源对象内部的指针/资源所有权转移给新对象,源对象的容器会变成空的(但依然是合法的对象,可以被重新赋值或销毁)。但对于int这种没有动态资源的类型,没有什么可以转移的,所以移动就是复制。

总结一下:你这里的“移动”本质上就是一次拷贝,源对象根本没被改动,当然能正常访问啦。

内容的提问来源于stack exchange,提问作者alexander.sivak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 05:22:36