【问题标题】:Cannot assign a reference that has a deleted copy constructor?无法分配具有已删除复制构造函数的引用?
【发布时间】:2021-11-15 09:16:45
【问题描述】:

我的情况是,我需要为一个类实现移动构造函数和移动赋值运算符,该类包含对具有已删除复制因子和复制分配运算符的对象的引用,基本上如下所示:

class MoveOnlyThing
{
public:
    MoveOnlyThing() = default;
    MoveOnlyThing(const MoveOnlyThing&) = delete;
    MoveOnlyThing& operator=(const MoveOnlyThing&) = delete;
};

class Holder
{
public:
    Holder(MoveOnlyThing& t)
    : mThing(t)
    {
    }
    
    Holder(Holder&& other)
    : mThing(other.mThing)
    {
    }
    
    Holder& operator=(Holder&& other)
    {
        mThing = other.mThing;
        return *this;
    }
    
    MoveOnlyThing& mThing;
};

现在,问题是,mThing = other.mThing; 的分配正在发出错误:

main.cpp:40:16: error: overload resolution selected deleted operator '='
        mThing = other.mThing;
        ~~~~~~ ^ ~~~~~~~~~~~~
main.cpp:20:12: note: candidate function has been explicitly deleted
    MoveOnlyThing& operator=(const MoveOnlyThing&) = delete;
           ^

提出了两个问题;

  1. 我们如何处理这个问题?实现 Move Constructor,然后用它来实现 Move-Assignment Operator?
  2. 我没有意识到在这种情况下编译器会在重新分配现有引用时生成一个副本。谁能解释一下?

【问题讨论】:

  • 您无法指定参考。仅初始化。
  • 你误解了mThing = other.mThing;的意思。这并不意味着“为引用mThing 分配一个新值”,而是“为(mThing 指向的对象)分配一个新值”。引用隐式执行间接,任何时候您使用引用的名称,您实际上都会得到它所指向的对象
  • @BenVoigt 是的,这是正确的,所以实际上它尝试调用复制构造函数的原因是分配给 原始对象 感谢您指出这一点
  • 您需要std::move() 才能调用MoveOnlyThing 的移动赋值运算符:mThing = std::move(other.mThing);

标签: c++ reference c++17 copy-constructor move-assignment-operator


【解决方案1】:

cannot reassign a reference

为了存储可以复制和重新分配的引用,有一个特定的类std::reference_wrapper。您需要做的就是将mThing 声明为

std::reference_wrapper<MoveOnlyThing> mThing;

工作示例:

#include <functional>

class MoveOnlyThing
{
public:
    MoveOnlyThing() = default;
    MoveOnlyThing(const MoveOnlyThing&) = delete;
    MoveOnlyThing& operator=(const MoveOnlyThing&) = delete;
};

class Holder
{
public:
    Holder(MoveOnlyThing& t)
    : mThing(t)
    {
    }
    
    Holder(Holder&& other)
    : mThing(other.mThing)
    {
    }
    
    Holder& operator=(Holder&& other)
    {
        mThing = other.mThing;
        return *this;
    }
    
    std::reference_wrapper<MoveOnlyThing> mThing;
};

int main()
{
    MoveOnlyThing m;
    Holder h(m);
    MoveOnlyThing m_new;
    Holder h2(m_new);
    h2 = std::move(h);
    Holder h3(std::move(h2));
    
    return 0;
}

live on Coliru

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 2013-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多