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
In the copy assignment operator, other can be constructor using a copy constructor or a move constructor (if other is initialized with an rvalue, it could be move-constructed --if move-constructor defined--). If it is copy-constructed, we will be doing 1 copy and that copy can't be avoided.
The move assignment operator takes an r-value reference only e.g. In the copy assignment operator, other can be constructor using a copy constructor or a move constructor (if other is initialized with an rvalue, it could be move-constructed --if move-constructor defined--).
A class can have multiple move assignment operators, e.g. both T& T::operator=(const T&&) and T& T::operator=(T&&). If some user-defined move assignment operators are present, the user may still force the generation of the implicitly declared move assignment operator with the keyword default.
It is unspecified whether virtual base class subobjects that are accessible through more than one path in the inheritance lattice, are assigned more than once by the implicitly-defined move assignment operator (same applies to copy assignment).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With