ZHOU
ZHOU

Reputation: 1191

Can I write both copy and move assignment operators for a class?

These are my prototypes,

MyClass& operator=(MyClass rhs);   // copy assignment
MyClass& operator=(MyClass &&rhs); // move assignment

But when I call

MyClass a, b;
a = std::move(b);

, there is an error.

556 IntelliSense: more than one operator "=" matches these operands:
        function "MyClass::operator=(MyClass rhs)"
        function "MyClass::operator=(MyClass &&rhs)"
        operand types are: MyClass = MyClass    

And the compiler returns:

Error   56  error C2593: 'operator =' is ambiguous  

Upvotes: 5

Views: 2407

Answers (1)

Overload resolution is ambiguous because when you pass an rvalue, both MyClass and MyClass && can be directly initialised by it.

If you want to provide a different implementation of copy and move assignment, the customary way is to take the copy assignment operator's parameter by const reference:

MyClass& operator=(const MyClass &rhs);   // copy assignment
MyClass& operator=(MyClass &&rhs); // move assignment

Done like this, the move assignment operator is a strictly better match for a (non-const) rvalue argument and so it's chosen by overload resolution.

An alternative approach, called copy-and-swap, is to provide just the assignment operator, take the parameter by value, and use swap to implement it:

MyClass& operator=(MyClass rhs)
{
  swap(*this, rhs);
  return *this;
};

This reuses the copy/move constructor for the assignment. It requires you to have implemented a swap function, which should be non-throwing.

The downside of this approach is that sometimes, manually implementing copy assignment can be cheaper than performing copy construction followed by a move.

Upvotes: 11

Related Questions