编译器错误 C2280,试图引用已删除的函数 operator=

Posted

技术标签:

【中文标题】编译器错误 C2280,试图引用已删除的函数 operator=【英文标题】:Compiler error C2280, attempting to reference a deleted function operator= 【发布时间】:2017-12-10 02:35:21 【问题描述】:

我正在编写一个大富翁游戏。而且我真的很喜欢排序功能,它可以生成漂亮干净的输出,在这种情况下,可以按组对玩家拥有的属性进行排序。

首先这是我的属性排序功能

bool propertySort(Property a, Property b)  return a.getGroup() <  b.getGroup(); 

现在,玩家拥有这些属性的列表。

#pragma once
#include <string>
#include <vector>
#include "Dice.h"
#include "Property.h"

class Player

public:
    ...
private:
    int curMoney 1500 ;
    int curLocation 0 ;
    int playerNum 0 ;
    std::string name;
    std::vector<Property> ownedProperties;
    int curDiceRoll;
;

如您所见,它是底部的私有属性,已初始化为 0 个属性。

因此,在我的 main 属性分类器中,我会将属性显示在板上供玩家查看,分类器功能不断给我错误 C2280。我知道正是这个排序函数引发了这个错误,因为如果我注释掉排序行,程序运行良好。我敢肯定,由于我是初学者,因此我不知道这是显而易见的事情。如果有人能提供关于它是什么的见解,那就太好了,谢谢!

void viewProperties(Player& p)

    string prompt = "Select a player to view their properties";
    vector<string> playerNames;
    for (Player p : players)
    
        playerNames.push_back(p.getName());
    
    Menu propertiesMenuSelection prompt, playerNames ;
    vector<Property> propertiesOfSelectedPlayer = players[propertiesMenuSelection.getChoice()].getOwnedProperties();
    sort(propertiesOfSelectedPlayer.begin(), propertiesOfSelectedPlayer.end(), propertySort);

    system("CLS");

如果这有帮助,这里是 Property 类

#pragma once
#include "Space.h"
#include <array>
#include <vector>

extern std::vector<Player> players;
class Property : public Space

public:
    Property(std::string name, std::vector<int> values);
    ~Property();
    void run(Player&) override;
    std::vector<std::string> boardOut() const override;
    std::string getName() const override;
    ...
private:
    std::string name;
    int group;
    int price;
    int buildingCost;
    int buildings;
    Player* ownerPtr = nullptr;
    std::array <int, 6> rent;
    const std::array <std::string, 10> groups "Brown", "Light Blue", "Pink", "Orange", "Red", "Yellow", "Green", "Dark Blue", "Railroad", "Utility" ;
;

这里是要求非常简单的空间类。

#pragma once
#include <string>
#include <vector>

class Player;

class Space

public:
    virtual void run(Player&) = 0;
    virtual std::string getName() const = 0;
    virtual std::vector<std::string> boardOut() const = 0;
;

【问题讨论】:

const std::array -- 这个成员变量可能是副本不可用的原因。 因为您不能分配给const 变量。愚蠢的例子:ideone.com/AieNNX 这里有一个更好的错误消息:ideone.com/6RiXzJ 现在我想起来了,这种情况很少见,您需要赋值运算符而不需要需要the rest of the big three。凉爽的。我现在有一个例子! @Alex -- 用外行的话来说,编译器无法弄清楚你想对该成员做什么,因为它是const。 Here is an old, but related article from Dr. Dobbs 【参考方案1】:

删除的函数是赋值运算符。无法分配Property,因为无法分配const 成员groups。对此最合乎逻辑的解决方案是将groups 声明为static,以便Property 的所有实例共享它并且不需要分配它。例如:

static const std::array <std::string, 10> groups;

groups 的存储空间需要在类定义之外进行分配和初始化:

const std::array <std::string, 10> Property::groups "Brown", "Light Blue", "Pink", 
                                                     "Orange", "Red", "Yellow", "Green", 
                                                     "Dark Blue", "Railroad", "Utility" ;

TL;DR

赋值运算符的默认行为是将源的所有成员复制到目标中,而不对副本应用任何智能。这意味着一个非常简单的例子

class test

public:
    const int a = 10;
;

会生成等价的

test& operator=(const test & src)

    a = src.a;
    return *this;

这是不可能的,因为aconst,即使没有更改也无法更改。

您可以添加自己的赋值运算符

test& operator=(const test & src)

    // deliberately does not assign a = src.a
    return *this;

但您想要这样做的唯一原因是如果没有方法可以在初始化时更改a 的值。如果您无法更改a,则test 的所有实例都具有相同的a 值,并且a 也可能是static 成员。

两个tests 的a 值不同的失败示例:

int main()

    test a11; // a const variable cannot be changed after initialization, 
                // but this initializes a to 11.
    test b;     // uses the default of 10

    std::cout << a.a << ',' << b.a; // output 11,10
    a = b; //this can't really be be done. a can never equal b

【讨论】:

完美!多么棒的解释。那个静态解决方案正是我需要和实现的,非常感谢! @Alex 没问题。帮助您为时已晚,但希望下一个遇到此问题的人能找到它。 我的想法完全正确,如果其他人遇到此错误,如果您使用类似 sort 的东西并且它不知从何而来,这可能会非常令人困惑。希望他们能找到这个问题,看看你的答案。也许他们会意识到无限制地使用非静态 const 是多么危险。这对我和其他人来说都是很棒的一课!

以上是关于编译器错误 C2280,试图引用已删除的函数 operator=的主要内容,如果未能解决你的问题,请参考以下文章

VS2019 C++ 错误 C2280 试图引用已删除的函数 inl

C++错误C2280 - 试图引用一个已删除的函数 - 在基元类型上。

C++ 错误(C2280)试图访问已删除的函数 [关闭]

试图找到已删除的函数

std::mutex 引起的 C2280 尝试引用已删除的函数

调用递归函数时出现编译器错误 - “试图引用已删除的函数”