assignment operator return a reference to *this in C++
I read about this from "Effective c++" ,this is Col.10. It say it's a good way to have assignment operators return a reference to *this. I wrote a code snippet to test this idea. I overridden the assignment operator here.And tested it. Everything is fine. But when I remove that operator overriding, everything is the开发者_如何学Go same. That means, the chaining assignment still works well. So, what am I missing? Why is that? Need some explanation from you guys, THank you.
#include <iostream>
using namespace std;
class Widget{
public:
Widget& operator=(int rhs)
{
return *this;
}
int value;
};
int main()
{
Widget mywidget;
mywidget.value = 1;
Widget mywidget2;
mywidget2.value = 2;
Widget mywidget3 ;
mywidget3.value = 3;
mywidget = mywidget2 = mywidget3;
cout << mywidget.value<<endl;
cout << mywidget2.value<<endl;
cout << mywidget3.value<<endl;
}
If you remove completely the operator=
method, a default operator=
will be created by the compiler, which implements shallow copy1 and returns a reference to *this
.
Incidentally, when you write
mywidget = mywidget2 = mywidget3;
you're actually calling this default operator=
, since your overloaded operator is designed to work with int
s on the right side.
The chained assignment will stop working, instead, if you return, for example, a value, a const
reference (=>you'll get compilation errors) or a reference to something different from *this
(counterintuitive stuff will start to happen).
Partially related: the copy and swap idiom, i.e. the perfect way to write an assignment operator. Strongly advised read if you need to write an operator=
- The default
operator=
will perform as if there were an assignment between each member of the left hand operand and each member of the right hand one. This means that for primitive types it will be a "brutal" bitwise copy, which in 90% of cases isn't ok for pointers to owned resources.
The question touches two different concepts, whether you should define operator=
and whether in doing so you should return a reference to the object.
You should consider the rule of the three: if you define one of copy constructor, assignment operator or destructor you should define the three of them. The rationale around that rule is that if you need to provide a destructor it means that you are managing a resource, and in doing so, chances are that the default copy constructor and assignment operator won't cut it. As an example, if you hold memory through a raw pointer, then you need to release the memory in the destructor. If you don't provide the copy constructor and assignment operator, then the pointer will be copied and two different objects will try to release the memory held by the pointer.
While a pointer is the most common example, this applies to any resource. The exception is classes where you disable copy construction and assignment --but then again you are somehow defining them to be disabled.
On the second part of the question, or whether you should return a reference to the object, you should. The reason, as with all other operator overloads is that it is usually a good advice to mimic what the existing operators for basic types do. This is sometimes given by a quote: when overloading operators, do as int
s do.
Widget& operator=(int rhs)
This allows you to assign an int to a Widget - e.g. mywidget = 3;
Make a Widget& operator=(Widget const & rhs)
- it'll be called for your mywidget = mywidget2 = mywidget3;
line.
You do not need an operator=(Widget const & rhs)
though - the default should do fine.
Also, it may be a good idea to add e.g. cout << "operator=(int rhs)\n";
to your custom operator - then you'd see that it didn't get called at all in your code.
精彩评论