3

Can someone explain why the move assignment operator is (usually) declared as

Foo& operator=(Foo&&);

Why return a reference and not e.g. Foo or Foo&&? I understand why we want this for the regular assignment operator, due to associativeness rules as (a=b)=c being logically broken (although still compilable) if not returned by reference, but why is this the case when the RHS is a rvalue (xvalue/prvalue)?

vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 1
    It's not at all clear what you're asking. You can't return "the object itself" except by reference. If you mean "why not return a copy of the object", then that only works if the type is copyable, and even then copying might be more expensive than you'd like. `(a=b)=c` requires the first expression `(a=b)` to be an _lvalue_ whatever the argument type of the assignment operator, so you have to return a reference if you want to support that. – Mike Seymour Mar 27 '15 at 01:37
  • @MikeSeymour I changed the question, why not just return `Foo`? or even `Foo&&`? What are the "chain" rules that will be broken? – vsoftco Mar 27 '15 at 01:39
  • Returning `Foo` is potentially expensive, and impossible if the type isn't copyable, as I said. Returning `Foo&&` is just weird; you don't want things mysteriously turning into _rvalues_ so that e.g. `f(a=b)` unexpectedly moves from `a` without you telling it to. – Mike Seymour Mar 27 '15 at 01:42
  • @MikeSeymour thanks, good point with this, you should post (if you want) an answer, as I don't think this issue is super obvious, although now it makes a lot of sense. – vsoftco Mar 27 '15 at 01:44
  • Another way of looking at it. If all you wanted was an rvalue and you were ok doing a copy, you could always do `Foo&& x = Foo(y);` This would be the same in my mind as a move operator on y that does a copy so in that case the move operator would be redundant on top of the copy constructor. – Pace Mar 27 '15 at 01:47
  • @Pace, correct, I realized now that the copy idea was just plain stupid. Now also figured out why `Foo&&` as a return type is just not the way to go, so the only reasonable remaining return type is `Foo&`. – vsoftco Mar 27 '15 at 01:49
  • The duplicate is titled "copy assignment operator" but it should really read "copy/move assignment" as everything is the same – M.M Mar 27 '15 at 02:26
  • @MattMcNabb thanks for finding the dupe, I didn't jump into it... probably because I knew why it's OK for copying (so the title was misleading), but didn't really understand why it's OK for move. – vsoftco Mar 27 '15 at 02:27

1 Answers1

5

Returning Foo is potentially expensive, and impossible if the type isn't copyable. It's also surprising: (a=b)=c would create a temporary and assign c to that, when you'd expect both assignments to be to a.

Returning Foo&& is just weird; you don't want things mysteriously turning into rvalues so that e.g. f(a=b) unexpectedly moves from a without you telling it to.

Returning Foo& is the conventional way to make the operator behave in an unsurprising way if you chain it.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644