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

持有删除拷贝构造的对象引用的类如何实现移动赋值运算符?

问题解答

问题1:报错处理方案

核心根本原因:你代码中的mThing是左值引用类型,C++规定引用一旦完成初始化就无法重新绑定,你写的mThing = other.mThing并不是修改引用的绑定目标,而是对mThing指向的MoveOnlyThing对象执行赋值操作,自然触发了被删除的拷贝赋值报错。

根据你的实际设计需求,有两种解决路径:

  • 场景1:移动Holder时仅需要转移对MoveOnlyThing对象的绑定关系,不需要操作对象本身的赋值
    这种场景不能使用引用作为成员,必须替换为指针类型(只有指针支持修改指向目标),修改后的代码示例:
    class Holder
    {
    public:
        Holder(MoveOnlyThing& t)
        : mThing(&t)
        {
        }
        
        Holder(Holder&& other) noexcept
        : mThing(other.mThing)
        {
            other.mThing = nullptr; // 可选,按需决定是否置空原Holder的指针
        }
        
        Holder& operator=(Holder&& other) noexcept
        {
            if (this != &other) {
                mThing = other.mThing;
                other.mThing = nullptr;
            }
            return *this;
        }
    private:
        MoveOnlyThing* mThing = nullptr;
        // 可对外提供返回引用的getter隐藏指针实现
        // MoveOnlyThing& getThing() { return *mThing; }
    };
    
  • 场景2:移动Holder时确实需要将源Holder绑定的MoveOnlyThing对象移动赋值到当前Holder绑定的对象
    需要做两处修改:
    1. 给MoveOnlyThing添加移动赋值运算符:你显式删除了拷贝赋值运算符后,编译器不会自动生成移动赋值运算符,需要手动声明:
      class MoveOnlyThing
      {
      public:
          MoveOnlyThing() = default;
          MoveOnlyThing(const MoveOnlyThing&) = delete;
          MoveOnlyThing& operator=(const MoveOnlyThing&) = delete;
          // 新增移动赋值运算符,可default或自定义实现
          MoveOnlyThing& operator=(MoveOnlyThing&&) = default;
      };
      
    2. 修改Holder的移动赋值代码,将other.mThing转为右值触发移动赋值:
      Holder& operator=(Holder&& other)
      {
          mThing = std::move(other.mThing);
          return *this;
      }
      

问题2:引用赋值触发拷贝操作的原理

C++中的引用本质是对象的别名,没有独立的存储空间,一旦在构造阶段完成绑定,后续所有对引用的操作都会直接作用在它绑定的对象上,不存在任何语法可以修改引用的绑定目标。

你代码中mThing = other.mThing的实际执行逻辑等价于:对当前Holder的mThing引用绑定的MoveOnlyThing实例,执行赋值运算符,传入参数是other.mThing引用绑定的MoveOnlyThing实例。
因为other.mThing是左值,重载解析会优先匹配参数为const MoveOnlyThing&的拷贝赋值运算符,而你已经显式删除了该函数,所以编译器直接抛出错误。
额外说明:你的移动构造没有报错是因为移动构造处于对象初始化阶段,成员初始化列表中的mThing(other.mThing)是在做引用绑定,而非赋值操作,不会调用任何MoveOnlyThing的赋值函数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:27:06