引用类成员的赋值运算符

22
只要我的前一个问题Overloaded assignment operator causes warning about recursion引发了新的问题,我就有充分的理由将其发布为新问题。 我的类Player中有一个引用类型的成员,并且我想要实现这个类的复制构造函数和赋值运算符(=)。 我必须提到的是,目的是使函数vector.erase正常工作,因为在我看来,否则它无法正常工作。 我使用向量: vector allPlayers; Player类的成员为:
class Player
{

  private:
  int ID;
  int pMoney;
  int doubleIndicator;
  int squarePosition;
  Bank& bank;
  string pName;
  Square* capturedSquare;
  multimap<string, PropertySquare*> squaresColBought;
  multimap<string, House*> housesColBuilt;

}

如果我想要实现赋值运算符,是否有必要避免使用引用作为类成员?那么 Map 成员又如何呢?最终应该如何实现赋值运算符?

我不知道的另一个极其重要的问题是:当我删除保存 Player 的 vector 的迭代器时,指针类成员指向的对象会发生什么情况?有什么帮助吗?


另一个问题,首先 :) - xtofl
你希望赋值运算符对银行执行什么操作? - fredoverflow
FredOverflow:只需将银行复制到lhs对象即可。 - arjacsoh
3个回答

25

C++中的“引用(reference)”只能进行初始化,而不能进行赋值操作:

int value1(1), value2(2);
int& ref1 = value1; // OK
int& ref2; // compile error: reference not initialized
int& ref3=ref1; // OK: ref3 refers to the same variable as ref1
ref1=value2; // equivalent to 'value1=value2'.
因此,一个包含引用的对象只能被初始化,而不能进行赋值!因此,如果您需要对一个类进行赋值,那么该类就不能有引用成员变量。(实际上,该类可以有引用成员变量,但是赋值操作无法使这些成员指向另一个位置)
思考一下这个问题,这很有道理:
引用概念定义了另一个变量的“别名”。别名意味着您对引用所做的任何操作实际上都会对所引用的位置进行操作。当您对此别名应用赋值时,实际上是对所引用的位置进行赋值。如果通过赋值可以使引用指向不同的位置,则引用的目的将丧失。
如果您需要后者,应该使用指针。

10

如果你需要一个赋值运算符,我建议不要使用引用成员。相反,使用(智能)指针,你只需要这样做:

Player &operator=(Player const &other)
{
    bankPtr = other.bankPtr;
    // copy other members
}
在当前情况下,bank = other.bank 将会复制 other.bank 的内容而不是将 this->bank 指向 other.bank 所引用的内容。
至于那些类型为multimap的成员,它们可以被无问题地复制,但要注意你会得到键(因为它们是string类型)的“深层”副本,但值的“浅”指针副本,所以你最终会得到共享状态。你可能需要使用shared_ptr来处理值。

1
如果所引用的对象不可为空且/或属于所有者,则使用std::reference_wrapper更好。它具有正确的赋值语义(重新绑定)。 - underscore_d

-1

这确实是对C++设计的一种hack,但你可以在'this'上使用placement new来实现。例如:

MyClass::MyClass(ReferenceType& referenceTarget):
    myReference(referenceTarget)
{}

MyClass& MyClass::operator=(const MyClass& other)
{
    new (this) MyClass(other.myReference);
    return *this;
}

1
我知道为什么这个答案收到了3个踩。如果(并且仅当)类具有非平凡的非引用成员,则placement new会创建潜在的内存泄漏。然而,我仍然认为它是一个有用的技巧,前提是“只有如果”条件不存在。 - Zhou
1
这里的踩是公平的,我不会自己推荐给任何人,但是是的,它需要一个我没有提供的解释。我只有一个意图,就是给出一个可能的变体,完全回答问题,而不评估它有多糟糕,投票就是为了这个目的。在某些情况下,您关于潜在内存泄漏的看法是正确的。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接