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

空自定义移动构造函数下B类成员地址输出异常的技术疑问

理解移动构造函数行为的常见误区

你的问题核心是对std::move和移动构造函数的职责存在误解,我们一步步拆解:

1. std::move不会自动修改源对象

std::move(obj1)的作用仅仅是将左值obj1转换为右值引用类型,让编译器可以匹配到移动构造函数,但它不会对obj1的成员做任何修改。

你的B类移动构造函数是空的(标记Doubt 1的位置),所以当执行B obj2 = std::move(obj1);时:

  • obj1的所有成员完全保持原来的状态,它的mp_Val依然指向之前创建的Temp对象(地址0xd48030),自然不会变成nullptr(也就是你预期的0)。

2. 空移动构造函数会导致目标对象成员未初始化

C++中,如果类的成员变量在构造函数中没有被显式初始化,那么它会保留未定义的垃圾值。

你的B移动构造函数没有给obj2.mp_Val赋值,所以obj2.mp_Val的地址0x400880是随机的垃圾内存地址,这也是为什么你看不到Temp默认构造函数的调用——因为obj2.mp_Val根本没有被初始化为任何Temp对象的指针,既没有新创建Temp,也没有从obj1转移指针。

3. 正确的移动构造函数应该怎么写?

移动构造函数的职责是转移源对象的资源,并将源对象置为安全的空状态,避免后续操作(比如析构)导致double free。修改你的B移动构造函数如下:

B(B&& in){ 
    std::cout << "Class B MOVE CTOR" << std::endl;
    // 转移源对象的资源
    mp_Val = in.mp_Val;
    // 将源对象置为空,防止后续操作访问无效资源
    in.mp_Val = nullptr;
}

修改后再运行,你会看到:

  • obj1.mp_Val的输出变成0(nullptr)
  • obj2.mp_Val的地址和原来obj1的地址一致
  • 全程不会调用任何Temp的构造函数,因为我们只是转移了指针所有权,没有创建新的Temp对象

总结

移动语义不是自动生效的,它完全依赖你编写的移动构造/赋值函数的逻辑:

  • 空的移动构造函数什么都不会做,目标对象成员未初始化,源对象状态不变
  • std::move只是类型转换工具,不负责资源转移或清空源对象

内容的提问来源于stack exchange,提问作者Upayan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:33:20