gpt4 book ai didi

c++ - C2280 : attempting to reference a deleted function (union, 结构体,复制构造函数)

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:33:59 25 4
gpt4 key购买 nike

当我尝试在 Visual Studio 2015 中编译以下最小示例时,我遇到了误导性错误消息的问题:

class Vector
{
float x;
float y;

public:

Vector(float x, float y) : x(x), y(y) {}
Vector& operator = (const Vector& v) { x = v.x; y = v.y; return *this; }
//Vector(Vector&&) = default;
};


class Rect
{
public:
union {
struct {
Vector p1, p2;
};

struct {
float p1x, p1y, p2x, p2y;
};
};

Rect() : p1(0,0), p2(0,0) {}
Rect(Vector& p1, Vector& p2) : p1(p1), p2(p2) {}

/*Rect(const Rect&) = default;
Rect& operator=(const Rect&) = default;
Rect& operator=(Rect&&) = default;
Rect(Rect&&) = default;*/
};


int main()
{
Rect test = Rect();
test = Rect();
return 0;
}
我收到以下错误消息:

1>...main.cpp(56): error C2280: 'Rect &Rect::operator =(const Rect &)': attempting to reference a deleted function

1>...main.cpp(50): note: compiler has generated 'Rect::operator =' here


编译器试图告诉我,类 Rect 的复制构造函数是一个被删除的函数。所以我尝试添加各种额外的(复制)构造函数和赋值运算符,如下所示,但没有成功:
Rect(const Rect&) = default;
Rect& operator=(const Rect&) = default;
Rect& operator=(Rect&&) = default;
Rect(Rect&&) = default;
我认识到错误实际上不是由 Rect 类引起的。当我评论该行时
Vector& operator = (const Vector& v) { x = v.x; y = v.y; return *this; }
错误消失了,当我想保留这一行时,我必须添加以下行:
Vector(Vector&&) = default;
然而,这个问题似乎只有当我在我的 Rect 类中使用 union 和结构时才会出现。
所以我不知道,我的错误实际上是在哪里引起的,或者只是错误消息指向了错误的类。

最佳答案

重复错误信息:

main.cpp(56): error C2280: 'Rect &Rect::operator =(const Rect &)': attempting to reference a deleted function



这很清楚:成员函数 operator=带参数 const Rect &delete d,但您的代码尝试在行 test = Rect(); 上调用它.

然后你说:

The compiler tries to tell me that, the copy constructor of class Rect is a deleted function



但是,您误读了错误。错误是关于函数 operator = ,称为复制赋值运算符。这是一个与复制构造函数不同的函数,它看起来像 Rect::Rect(const Rect &) .

你说你尝试添加:

Rect& operator=(const Rect&) = default;



然而,这不会有什么区别。编译器生成 operator=功能是 delete d 因为编译器不可能生成一个(对此的解释如下);写作 = default;不会改变这一点。你必须真正为 operator= 写你自己的 body 它执行您希望在分配发生时发生的操作。

在标准 C++ 中,不允许有匿名结构,更不用说匿名 union 中的匿名结构了。所以你真的是一个人在这里。您的编译器使用的关于 operator= 的规则、复制构造函数等不在任何标准中。

您的一个版本 Rect在标准 C 中可编译的内容可能如下所示:
class Rect
{
public:
struct S1 {
Vector p1, p2;
S1(Vector p1, Vector p2): p1(p1), p2(p2) {}
};
struct S2 {
float p1x, p1y, p2x, p2y;
};

union {
struct S1 s1;
struct S2 s2;
};

Rect() : s1({0, 0}, {0, 0}) {}
Rect(Vector p1, Vector p2) : s1(p1, p2) {}
};

到现在为止还挺好。对于此类,隐式声明的 operator=定义为删除。要了解原因,我们首先必须查看匿名 union 的隐式声明的特殊函数,因为类的隐式声明函数的行为取决于对其每个成员的相同操作的行为。

union 的相关规则是 C++14 [class.union]/1:

If any non-static data member of a union has a non-trivial default constructor , copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor, the corresponding member function of the union must be user-provided or it will be implicitly deleted for the union.


Vector有一个不平凡的 operator= ,因为你为它写了你自己的 body 。因此 S1有不平凡的 operator= ,因为它有一个非平凡的成员 operator= ,因此根据上面的引用,隐式声明的 operator= union 是 delete d.

请注意,复制构造函数没有错误: Vector确实有一个简单的复制构造函数,所以 union 也有。

要修复此错误,您可以执行以下两项操作之一:
  • 更改 Vector::operator=变得微不足道,要么完全删除您的定义,要么使其成为= default;
  • 写信 operator=Rect类(class)

  • 现在,您将如何编写自己的 operator= ?你做吗 s1 = other.s1; ,或者你做 s2 = other.s2; ?编译器自己无法知道,这就是隐式声明 operator= 背后的原因。被删除。

    现在,您似乎忽略了(无意或有意)C++ 中有关事件成员的规则:

    In a union, at most one of the non-static data members can be active at any time



    这意味着如果 s1是最后一个成员集,那么你必须做 s1 = other.s1; .或者如果 s2是最后一个成员集,你必须做 s2 = other.s2; .

    复制构造函数不会遇到这个问题,因为它是微不足道的:编译器可以生成一个按位的拷贝,并且无论哪个成员处于事件状态,它都会正确地实现该拷贝。但是由于您的 operator=是非平凡的,那是不可能的。

    例如,假设您实际上有一个 union std::stringstd::vector - 按位复制对其中任何一个都不起作用,您需要知道哪个是事件的才能执行复制。

    重申: 在标准 C++ 中,除了最近写入 的成员之外,不允许读取 union 成员。 .您不能将 union 用于别名。 C++ 有其他语言工具可以使用 union 别名实现您在 C 中所做的事情, see here for more discussion .

    根据您为匿名结构选择的成员,我怀疑这就是您打算做的。如果你真的想继续使用这种方法,依靠你的编译器将 union 别名作为非标准扩展来实现,那么我的建议是使用默认的 operator=为您 Vector类(class)。

    关于c++ - C2280 : attempting to reference a deleted function (union, 结构体,复制构造函数),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33921710/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com