Copy assignment operator

A copy 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 without 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 copy assignment operator (same applies to move assignment).

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

# Example

#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
 
struct A
{
    int n;
    std::string s1;
 
    A() = default;
    A(A const&) = default;
 
    // user-defined copy assignment (copy-and-swap idiom)
    A& operator=(A other)
    {
        std::cout << "copy assignment of A\n";
        std::swap(n, other.n);
        std::swap(s1, other.s1);
        return *this;
    }
};
 
struct B : A
{
    std::string s2;
    // implicitly-defined copy assignment
};
 
struct C
{
    std::unique_ptr<int[]> data;
    std::size_t size;
 
    // user-defined copy assignment (non copy-and-swap idiom)
    // note: copy-and-swap would always reallocate resources
    C& operator=(const C& other)
    {
        if (this != &other) // not a self-assignment
        {
            if (size != other.size) // resource cannot be reused
            {
                data.reset(new int[other.size]);
                size = other.size;
            }
            std::copy(&other.data[0], &other.data[0] + size, &data[0]);
        }
        return *this;
    }
};
 
int main()
{
    A a1, a2;
    std::cout << "a1 = a2 calls ";
    a1 = a2; // user-defined copy assignment
 
    B b1, b2;
    b2.s1 = "foo";
    b2.s2 = "bar";
    std::cout << "b1 = b2 calls ";
    b1 = b2; // implicitly-defined copy assignment
 
    std::cout << "b1.s1 = " << b1.s1 << "; b1.s2 = " << b1.s2 << '\n';
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
CWG 1353C++98the conditions where implicitly-declared copy assignment operatorsare undefined did not consider multi-dimensional array typesconsider these types
CWG 2094C++11a volatile subobject made defaulted copyassignment operators non-trivial (CWG issue 496)triviality not affected
CWG 2171C++11operator=(X&) = default was non-trivialmade trivial
CWG 2180C++11a defaulted copy assignment operator for class T was not defined as deletedif T is abstract and has non-copy-assignable direct virtual base classesthe operator is definedas deleted in this case
CWG 2595C++20a copy assignment operator was not eligible if thereis another copy assignment operator which is moreconstrained but does not satisfy its associated constraintsit can be eligiblein this case

# See also