Move assignment operator

A move assignment operator is a non-template non-static member function with the name operator= that can be called with an argument of the same class type and copies the content of the argument, possibly mutating the argument.

# Notes

If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move), and selects the copy assignment if the argument is an lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.

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).

See assignment operator overloading for additional detail on the expected behavior of a user-defined move-assignment operator.

# Example

#include <iostream>
#include <string>
#include <utility>
 
struct A
{
    std::string s;
 
    A() : s("test") {}
 
    A(const A& o) : s(o.s) { std::cout << "move failed!\n"; }
 
    A(A&& o) : s(std::move(o.s)) {}
 
    A& operator=(const A& other)
    {
         s = other.s;
         std::cout << "copy assigned\n";
         return *this;
    }
 
    A& operator=(A&& other)
    {
         s = std::move(other.s);
         std::cout << "move assigned\n";
         return *this;
    }
};
 
A f(A a) { return a; }
 
struct B : A
{
    std::string s2; 
    int n;
    // implicit move assignment operator B& B::operator=(B&&)
    // calls A's move assignment operator
    // calls s2's move assignment operator
    // and makes a bitwise copy of n
};
 
struct C : B
{
    ~C() {} // destructor prevents implicit move assignment
};
 
struct D : B
{
    D() {}
    ~D() {} // destructor would prevent implicit move assignment
    D& operator=(D&&) = default; // force a move assignment anyway 
};
 
int main()
{
    A a1, a2;
    std::cout << "Trying to move-assign A from rvalue temporary\n";
    a1 = f(A()); // move-assignment from rvalue temporary
    std::cout << "Trying to move-assign A from xvalue\n";
    a2 = std::move(a1); // move-assignment from xvalue
 
    std::cout << "\nTrying to move-assign B\n";
    B b1, b2;
    std::cout << "Before move, b1.s = \"" << b1.s << "\"\n";
    b2 = std::move(b1); // calls implicit move assignment
    std::cout << "After move, b1.s = \"" << b1.s << "\"\n";
 
    std::cout << "\nTrying to move-assign C\n";
    C c1, c2;
    c2 = std::move(c1); // calls the copy assignment operator
 
    std::cout << "\nTrying to move-assign D\n";
    D d1, d2;
    d2 = std::move(d1);
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
CWG 1353C++11the conditions where defaulted move assignment operators aredefined as deleted did not consider multi-dimensional array typesconsider these types
CWG 1402C++11a defaulted move assignment operator that wouldcall a non-trivial copy assignment operator wasdeleted; a defaulted move assignment operator thatis deleted still participated in overload resolutionallows call to suchcopy assignmentoperator; made ignoredin overload resolution
CWG 1806C++11specification for a defaulted move assignment operatorinvolving a virtual base class was missingadded
CWG 2094C++11a volatile subobject made of a defaultedmove assignment operator non-trivial (CWG issue 496)triviality not affected
CWG 2180C++11a defaulted move assignment operator for class Twas not defined as deleted if T is abstract and hasnon-move-assignable direct virtual base classesthe operator is definedas deleted in this case
CWG 2595C++20a move assignment operator was not eligible if thereis another move assignment operator which is moreconstrained but does not satisfy its associated constraintsit can be eligible in this case
CWG 2690C++11the implicitly-defined move assignment operator forunion types did not copy the object representationthey copy the objectrepresentation

# See also