1
Type &Type::operator=(Type &&rhs)
{
if(this == &rhs) //is there any need of self-assignment . 
returh *this ;
}
...
}

//since it will be called on r-value so why self-assignment ??

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Hamza
  • 82
  • 9
  • 1
    `Type a; a = std::move(a);` Technically, it's not required at all anytime, though can be very helpful in Rule-of-[35]-subject classes, to get consistency for a small price. – bipll Dec 02 '18 at 10:37
  • With the code snippet from bipll you can figure it out yourself. Write a small class that manages an `int*` and implement move assignment for it without checking for self-assignment. How bug-free is it? – StoryTeller - Unslander Monica Dec 02 '18 at 11:12
  • If we write a class that has copy assignment operator and move assignment operator . so self assignment check in one (copy or move) operator is enough . rather than checking in both (copy and move) . – Hamza Dec 02 '18 at 12:39
  • For the stl, self move assignment is unspecified. See this [answer](https://stackoverflow.com/a/13127916/5632316) (by a top c++ committee member, and implementer of libc++) – Oliv Dec 02 '18 at 12:41
  • My opinion is to do as in the STL. But you can make an assert: `assert(this!=&rhs)` and see what happens. Otherwise you can specify it has a default semantic, like resetting the object. – Oliv Dec 02 '18 at 12:43
  • Finaly found a duplicate which was also answered by Howard Hinnant: https://stackoverflow.com/questions/9322174/move-assignment-operator-and-if-this-rhs – Oliv Dec 02 '18 at 12:54
  • @Hamzashah: Imagine `shared_ptr`'s move operation. It has to clear out its own data (possibly reducing the reference count of whatever it was managing), copy the bytes from the other pointer, and then null out the other `shared_ptr`'s data (no need to modify the reference count). Well, if the source and destination are *the same*, then step 1 will remove all pointers to the managed object, thus making steps 2 and 3 pointless. Oops. – Nicol Bolas Dec 02 '18 at 14:31

1 Answers1

3

Usually...

Suppose your class holds a pointer to some buffer that it allocates. Now, in a naive move-assignment operator, you would:

  • Free your own buffer
  • Assign the other object's buffer pointer to your buffer pointer
  • Assign null to the other object's buffer pointer, and perhaps set its size to 0

This will not make you dereference a null pointer, but - you've just lost all data in your buffer, which is likely not what you wanted, nor what the user expected.

... but not always

There is a (narrow) exception to the rule above: The case of your move-assignment operator being 'idempotent' for self-assignment. For example, if your assignment operator only involves assignment of the members - then it's safe to self-assign just like a regular assignment (trusting that the members' self-assignment implementations are valid). Nothing will be changed or lost.

This exception to the rule is indeed narrow, since the above is mostly true for the example I gave - in which case you would use the default move-assignment operator. Still, just because you don't find this check in someone's code does not mean there's a bug.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    "you've just lost all data in your buffer." Which is usually not a bad thing (do you have any case, where this is actually a problem?). The standard doesn't say that the data must be kept: http://eel.is/c++draft/utility.arg.requirements#tab:moveassignable. And indeed, for example, moving `std::vector` to itself will remove its content (both libc++ and stdlibc++). – geza Dec 02 '18 at 12:21
  • @geza: Always. after assigning `y` to `x` you expect `x` to have the same value as `y` had before (move or no move). – einpoklum Dec 02 '18 at 12:31
  • On the other hand, as you moved from `y`, it is not unexpected that its content is empty. So there are contradicting expectations in this case. That's why I ask, where does this mean actually a problem?. For example, "moving" `swap` still works (`tmp = move(a); a = move(b); b = move(tmp)`). Is there any algorithm, where this behavior (data-loss) causes a problem? It must have a reason that the standard doesn't require data be kept in this case. – geza Dec 02 '18 at 12:43
  • @geza Interesting reference: https://stackoverflow.com/a/9322542/5632316 – Oliv Dec 02 '18 at 12:51
  • @Oliv: He says: "For move assignment: x = std::move(y); one should have a post-condition that y has a valid but unspecified state." But there is another reasonable post-condition: `x` should be equal to what `y` was before the assignment. And it is violated. Which usually doesn't cause any problems (I haven't found any case yet). But it still can be unexpected. – geza Dec 02 '18 at 13:12
  • @gaza: You can't rely on anything happening to the contents of a moved object. There's no expectation-of-emptiness. – einpoklum Dec 02 '18 at 19:09