处理赋值运算符重载;你可以重新分配参考吗?

时间:2011-12-09 17:36:37

标签: c++ reference assignment-operator

如果您的类有一个引用变量,那么需要编写重载的赋值运算符。

我的印象是你只能在实例化时设置一次引用,因此无法执行以下操作:

MyClass& MyClass::operator=(const MyClass& rhs) 
{
    if (&rhs != this)
    {
        myReference = rhs.myReference;
    }
    return *this;
}

你如何解决这个问题?

编辑 - 好的,所以我被告知你不能在带引用的类上使用赋值运算符,很好。但是为什么视觉工作室会让我这样做呢?程序运行和一切。

5 个答案:

答案 0 :(得分:1)

不,你不能重新安排参考。

考虑:

int a = 42, b = 43;
int &ar = a;
ar = b;

编译器如何知道您尝试重置ar以引用b,而不是将a设置为{{1} }}?

您可以使用指针而非参考来解决此“问题”。

编辑:根据你的编辑,

  

好的,所以我告诉你不能在带有a的类上使用赋值运算符   参考,很好。但是为什么视觉工作室会让我这样做呢?该   程序运行和一切。

你的结论的前提是错误的。 可以在包含引用的类上使用赋值运算符。你不能做的是重新安排参考。如上面的代码所示,如​​果您尝试使用43重新分配引用,则不会重置ar = a;引用的内容,而是更改ar引用的值。< / p>

Visual Studio“让你做到了”,没有任何困难。误解正是Visual Studio允许您做的事情。它不会让你重新安置参考。它让你改变了反叛者的价值。这是一个例子,我希望能澄清这意味着什么。

ar

上面的代码建立了2个#include <iostream> #include <string> using namespace std; class Foo { public: void dump() const { cout << "Foo instance " << showbase << this << "\n"; } }; class Bar { public: Bar(Foo& foo) : foo_(foo) {} Bar& operator=(const Bar& rhs) { foo_ = rhs.foo_; return * this; } void dump() const { cout << showbase << "Bar instance " << this << "\t"; foo_.dump(); } private: Foo& foo_; }; int main() { cout << "foo1: "; Foo foo1; foo1.dump(); cout << "foo2: "; Foo foo2; foo2.dump(); cout << "bar1 :"; Bar bar1(foo1); bar1.dump(); cout << "bar2 :"; Bar bar2(foo2); bar2.dump(); bar2 = bar1; cout << "bar2 after assign :"; bar2.dump(); } 个对象(Foofoo1)并创建了2个foo2个对象,每个对象都引用了不同的Bar }。 FooBar,执行以下内容:

operator=

如果C ++允许您以这种方式重新设置引用,foo_ = rhs.foo_; 现在将引用foo_的其他实例。但是,事实并非如此。这不会改变Foo引用的内容。相反,它会在foo_本身上调用operator=。运行上面的代码,您会发现FooFoo的地址永远不会改变。如果您可以重新设置引用,它就会改变。

答案 1 :(得分:0)

您可以使用使用引用的类创建赋值运算符,但是这一行:

myReference = rhs.myReference;

不重新分配参考。如果重新分配引用引用的东西。因此,在该赋值之后,myReference和rhs.myReference现在不会引用同一个对象。但是他们现在提到的东西具有相同的值(或者对于那种类型的任何赋值意味着)。

如果需要可重新分配的引用,请使用指针。这就是他们的目的。事实上,在现代C ++中,这几乎是原始指针的唯一用途。如果您引用的对象是动态分配的,那么您应该将其放在shared_ptr中,并将myReference设为另一个shared_ptrweak_ptr

答案 2 :(得分:0)

用两个词 - 你不能。引用具有实际对象的语义,因此赋值运算符实际上将调用底层对象的赋值而不是引用本身。

答案 3 :(得分:0)

参考不能反弹。 (好吧,放置new可以,但不要这样做!)

但代码是合法的,即使它没有按照你的想法做到。它不是重新绑定或重新分配引用,而是分配给引用(引用的目标)。

答案 4 :(得分:0)

您的代码按照书面形式运行,但您重新分配参考。

myReference = rhs.myReference;

将rhs.myReference引用的对象分配给myReference。因此,假设在赋值&myReference != &(rhs.myReference)之前为真,它在赋值后仍然为真,但这些地址处的对象将包含相同的值(如果为myReference == rhs.myReference定义了operator==类型和工作在一个让我们说不成型的方式)。重新分配引用(这是不可能的)将意味着在赋值&myReference == &(rhs.myReference)之后将是真的。所以真正的问题是你想要做什么:你想将rhs.myReference引用的对象复制到this->myReference引用的对象(在这种情况下你的代码没问题),或者你想要make this->myReference引用与rhs.myReference相同的对象(这对于引用是不可能的,因此您需要使用指针)。