Why does the operator = return * this?

Let's say I want to override operator = so that I can do something like

 Poly p1; // an object representing a polynomial Poly p2; // another object of the same type p2 = p1; // assigns all the contents of p1 to p2 

Then in my operator = implementation I have something like this:

 Poly& Poly::operator=(const Poly &source) { // Skipping implementation, it already works fine… return *this; } 

Not against implementation, it is already working fine.

I am worried about what happens when you return *this ? I know that it returns a reference to an object, but does this happen?

 p2 = &p1 
+7
c ++ assignment-operator
source share
5 answers

You return *this so you can write normal C ++ = compound expressions, for example:

 Poly p1; //an object representing a polynomial Poly p2; Poly p2; // ... p3 = p2 = p1; //assigns all the contents of p1 to p2 and then to p3 

because this statement is basically:

 p3.operator=(p2.operator=(p1)); 

If p2.operator=(...) did not return *this , you would have nothing to pass to p3.operator=(...) .

+13
source share

p2 = p1 is short for p2.operator=(p1) . It simply calls your operator= function, which returns a link to p2 that you ignore. To make this clear, call it assign instead of operator= :

 Poly& Poly::assign(const Poly &source) { . . . return *this; } 

Now instead of p2 = p1 you should write

 p2.assign(p1); 

In this case, the result of the assign call is ignored, but you do not need to ignore it. For example, you can write:

 p3.assign(p2.assign(p1)); 

Using operator= instead of assign , it becomes

 p3 = (p2 = p1); 

but since assignment is right-associative, it can also be written as

 p3 = p2 = p1; 

This form of being able to do multiple assignments immediately comes from C and was saved in C ++ through the agreement to return *this to operator=() .

+5
source share

You might be tempted to make a copy-assign return void statement if you don't need chained assignments (as shown in other answers) anyway. After all, seconded assignments are often difficult to read and understand, so they cannot be considered an improvement.

However, the often forgotten aspect is that void operator=(Poly& const) means that your type will no longer fulfill the CopyAssignable concept, which requires a T& return type.

A type that does not conform to the CopyAssignable concept cannot be officially used for some operations with a standard container, for example std::vector::insert , which means that the next seemingly innocent piece of code gives undefined behavior, although this is probably fine working:

 #include <vector> struct Poly { void operator=(Poly const&) {} // Poly is not CopyAssignable }; int main() { std::vector<Poly> v; Poly p; v.insert(v.begin(), p); // undefined behaviour } 

As the C ++ standard explains in section 17.6.4.8/2.3, which talks about restrictions on programs that use the standard library:

(...) effects are undefined in the following cases:

(...) for types used as template arguments when instantiating template components , if type operations do not implement the semantics of the applicable requirements of subclause (...).

Of course, it is precisely because of the undefined behavior that the compiler is allowed to ignore the error and force the program to behave nicely, corresponding to the obviously intended behavior. But this is not required.

You should also bear in mind that you cannot predict all future uses of your Poly type. Someone might write some template function, such as:

 template <class T> void f(T const& t) { T t2; T t3 = t2 = t; // ... } 

This function will not work with your Poly class.

Just don't break this C ++ convention and you won't run into problems.

+4
source share

What happens when you return it?

In your example ( p2 = p1; ) nothing. The method copies p1 to p2 and returns a reference to the 'this' object, which the call code does not use.

In the code, for example p3 = p2 = p1; , the first call is p2 = p1 , which copies p1 to p2 and returns a reference to p2 . Then the calling code copies from this link in p2 to p3 (and ignores the link to p3 that is returned).

(Along the way: are you running your device tests so that p1 = p1 works correctly? It's easy to forget this case!)

+2
source share

Returning the link to the target allows a chain of binding (cascading), and operator overloading within the class follows the right-associative (click here for detailed rules for operator overloading)

 Poly a, b, c; a = b = c; 
0
source share

All Articles