【问题标题】:c++ deleted move assignment operator compilation issuesc++删除了移动赋值运算符编译问题
【发布时间】:2014-05-24 21:07:27
【问题描述】:

以下代码在 gcc 4.8.0 (mingw-w64) 和 -O2 -std=c++11 -frtti -fexceptions -mthreads 中失败

#include <string>

class Param
{
public:
    Param() : data(new std::string) { }

    Param(const std::string & other) : data(new std::string(other)) { }

    Param(const Param & other) : data(new std::string(*other.data)) { }

    Param & operator=(const Param & other) {
        *data = *other.data; return *this;
    }

    ~Param() {
        delete data;
    }

    Param & operator=(Param &&) = delete;


private:
    std::string * data;
};


int main()
{
    Param param;
    param = Param("hop");


    return 0;
}

出现错误:错误:使用已删除的函数'Param& Param::operator=(Param&&)' 上线:

param = Param("hop");

如果我删除移动赋值删除行,编译会很好。

应该没有默认的移动赋值运算符,因为有用户定义的拷贝构造函数、用户定义的拷贝赋值和析构函数,所以删除它应该不会影响编译,为什么会失败? 为什么分配根本不使用复制分配?

【问题讨论】:

  • 我不会评论你的问题,只是你使用了错误的构造函数。您应该使用构造函数的初始化列表,如下所示:Param():data(new std::string){},否则您将进行一些奇怪的初始化然后赋值。
  • 好的,我对代码做了一些更改以修复一些错误并回答 cmets,但这不会改变结果
  • = delete 的意思是“调用这个函数是错误的”,而不是“从重载集中删除这个函数”。
  • @Casey:我一直忘记这一点,我讨厌它。它应该将其从重载集中删除,并使用复制分配代替。
  • @MooingDuck :您编辑的问题是正确的,这是分配而不是构造。我仍然错误地假设编译器会将其优化为一个简单的构造函数,就好像我写了 Param param("hop");

标签: c++ c++11 constructor move-semantics


【解决方案1】:

您删除的函数正是您尝试在main 中使用的赋值运算符。通过明确将其定义为已删除,您声明它,同时说使用它是一个错误。因此,当您尝试从右值 (Param("hop")) 进行赋值时,编译器首先查看是否声明了移动赋值运算符。由于它曾经是并且现在是最佳匹配,它尝试使用它,只是发现它已被删除。因此错误。

这是另一个不使用特殊功能的机制示例:

class X
{
  void f(int) {}
  void f(short) = delete;
};

int main()
{
  X x;
  short s;
  x.f(s);  // error: f(short) is deleted.
}

删除已删除的f(short)会导致编译器选择未删除的f(int),从而编译不会出错。

【讨论】:

  • 好的,我用错了词,现在更正了。但是对于赋值,不需要移动语义,否则会破坏 c++99 代码。它应该回退到复制分配。如果我不删除它,就不应该有默认的移动分配。
  • 为什么尽管提到了我的回答的 old 版本,但该评论仍然得到支持,并且根本不适合当前的 all版本?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
  • 2018-09-21
  • 2017-11-21
  • 1970-01-01
  • 2020-04-09
相关资源
最近更新 更多