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 ??

7
  • 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. Commented Dec 2, 2018 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? Commented Dec 2, 2018 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) . Commented Dec 2, 2018 at 12:39
  • For the stl, self move assignment is unspecified. See this answer (by a top c++ committee member, and implementer of libc++) Commented Dec 2, 2018 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. Commented Dec 2, 2018 at 12:43

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

"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: 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: Always. after assigning y to x you expect x to have the same value as y had before (move or no move).
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 Interesting reference: stackoverflow.com/a/9322542/5632316
@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.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.