[英]dealing with assignment operator overloads; can you re-assign a reference?
如果您的类具有参考变量,则需要编写重载的赋值运算符。
我的印象是,您只能在实例化时设置一次引用,因此不能执行以下操作:
MyClass& MyClass::operator=(const MyClass& rhs)
{
if (&rhs != this)
{
myReference = rhs.myReference;
}
return *this;
}
你怎么解决这个问题?
编辑-好的,所以我被告知您不能在带有引用的类上使用赋值运算符,很好。 但是为什么Visual Studio让我这样做呢? 该程序运行,一切正常。
不,您不能重新放置参考。
考虑:
int a = 42, b = 43;
int &ar = a;
ar = b;
编译器怎样才能知道你正在尝试重新安装ar
指b
,和值没有设置a
以43
?
您可以通过使用指针而不是引用来解决此“问题”。
编辑:根据您的编辑,
好的,所以我被告知您不能在带有引用的类上使用赋值运算符,很好。 但是为什么Visual Studio让我这样做呢? 该程序运行,一切正常。
结论的前提是错误的。 您可以在包含引用的类上使用赋值运算符。 您不能做的是重新放置参考。 如上面的代码所示,如果您尝试使用ar = a;
重新分配引用ar = a;
您不会重新使用ar
所指的内容,而是更改ar
所指的值。
Visual Studio可以“轻松地做到这一点”。 误解恰恰是Visual Studio允许您执行的操作。 这不是让您重新设置参考。 它使您可以更改引用者的值。 这是一个示例,我希望它将阐明这意味着什么。
#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();
}
上面的代码建立了2个Foo
对象( foo1
和foo2
)并创建了2个Bar
对象,每个对象都有对不同Foo
的引用。 Bar
有一个operator=
,它执行以下操作:
foo_ = rhs.foo_;
如果C ++允许您以这种方式重新foo_
引用,则foo_
现在将引用Foo
的另一个实例。 但是,事实并非如此。 这不会改变foo_
所指的内容。 相反,它在Foo
本身上调用operator=
。 运行上面的代码,您将看到bar2
Foo
的地址永远不变。 如果您可以重新放置参考,它将改变。
您可以为使用引用的类创建赋值运算符,但以下行:
myReference = rhs.myReference;
不重新分配参考。 如果重新分配引用所指的东西。 因此,在分配之后,myReference和rhs.myReference现在不再引用同一对象。 但是他们现在所指的事物具有相等的值(或该类型的任何赋值方式)。
如果需要可重新分配的引用,请使用指针。 那就是他们的目的。 实际上,在现代C ++中,这几乎是原始指针剩下的唯一用途。 如果您要引用的对象是动态分配的,则应将其放在shared_ptr
,并使myReference成为另一个shared_ptr
或weak_ptr
。
用两个词-你不能。 引用具有实际对象的语义,因此赋值运算符实际上将为基础对象而不是引用本身调用赋值。
参考不能反弹。 (嗯,可以放置new
,但是不要那样做!)
但是该代码是合法的,即使它没有执行您认为的操作。 它不是重新绑定或重新分配引用,而是分配给引用对象(引用的目标)。
您的代码按编写的方式工作,但是您不会重新分配参考。
myReference = rhs.myReference;
将rhs.myReference引用的对象分配给myReference。 因此,假设在分配&myReference != &(rhs.myReference)
为true之前,分配之后仍为true,但是这些地址处的对象将包含相同的值(因此,如果operator==
则myReference == rhs.myReference
是为该类型定义的,并且可以说是一种非惊奇的方式)。 重新分配引用(这是不可能的)意味着分配后&myReference == &(rhs.myReference)
将为true。 所以真正的问题是你想要做什么:你想通过复制引用的对象rhs.myReference
成提到了一个this->myReference
(在这种情况下,你的代码是罚款),或做你想this->myReference
指向同一个对象rhs.myReference
(这是不可能的引用,所以你需要使用指针)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.