Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there situations when self-assignment is useful?

Tags:

It is commonly known that when implementing an assignment operator one has to protect against self-assignment, at least when the class has non-POD members. Usually it is (or is equivalent to):

Foo& operator=(const Foo& other) {   if (&other == this)      return *this;   ... // Do copy } 

What were the reasons for not inserting the self-assignment protection automatically? Are there use cases when self-assignment does something non-trivial and practically useful?

Foo& operator=(const Foo& other) {   if (&other == this)   {     // Do something non-trivial   }   else   {     // Do copy   }   return *this; } 

To summarize the answers and discussion by now

Looks like non-trivial self-assignment can never be really useful. The only option proposed was to put an assert there in order to detect some logical errors. But there are quite legitimate self-assignment cases like a = std::min(a, b), so even this option is highly dubious.

But there are two possible implementations of a trivial self-assignment:

  1. Do nothing if &other == this. Always work, though may have negative performance impact due to an extra branching. But in a user-defined assignment operator the test must be almost always explicitly made.
  2. Copy each member to itself. This is what is done by default. If the members use default assignment operators as well, it may be faster, because doesn't requre an extra branching.

I still don't see why the C++ standard could not guarantee that in a user-defined assignment operator &other != this. If you want no branching, use the default operator. If you are redefining the operator, some test is needed anyway...

like image 800
aparpara Avatar asked May 26 '19 18:05

aparpara


People also ask

What is self-assignment?

Definition of self-assignment : the act of assigning something (such as a task) to oneself working on/by self-assignment also : the task or work that is assigned Alexander came to Winged Foot in 1959 to shoot the U.S. Open. It was a self-assignment that resulted in a series of iconic photos … —

Why do we need to check for self-assignment in an assignment operator?

The general reason to check for self-assignment is because you destroy your own data before copying in the new one. This assignment operator structure is also not strongly exception safe.

How do you overload an assignment operator?

Assignment Operators Overloading in C++You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor. Following example explains how an assignment operator can be overloaded.


2 Answers

Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself. Consider the case where you have a user-provided assignment operator because each individual object has some kind of identifier, which you don't want to copy. Well, you can "copy" the other values just fine in self-assignment cases. So inserting an invisible self-assignment test is just adding a pointless and potentially costly conditional branch.

So it's not about self-assignment being useful; it's about self-assignment not always needing protection.

Furthermore, C++ generally doesn't like adding code like that to your code without you explicitly asking for it. It's typically done in terms of whole functions, not part of functions. Even destructor calls at the end of blocks are something you asked for when you put the object to be destroyed on the stack.

like image 63
Nicol Bolas Avatar answered Oct 12 '22 01:10

Nicol Bolas


There are algorithms where it can happen.

  1. You know the lhs and rhs might be the same but it is just simpler to do the assignment than check. E.g., consider a = std::min(a,b); - simpler and perhaps easier to understand than if (a > b) a = b; - now consider more complicated examples of similar things.

  2. You don't know whether lhs and rhs might be the same, because they may have been passed in from somewhere else.

These algorithms where it can happen are not uncommon.

like image 45
davidbak Avatar answered Oct 12 '22 03:10

davidbak