21.12 — Overloading the assignment operator
The copy assignment operator (operator=) is used to copy values from one object to another already existing object .
Related content
As of C++11, C++ also supports “Move assignment”. We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .
Copy assignment vs Copy constructor
The purpose of the copy constructor and the copy assignment operator are almost equivalent -- both copy one object to another. However, the copy constructor initializes new objects, whereas the assignment operator replaces the contents of existing objects.
The difference between the copy constructor and the copy assignment operator causes a lot of confusion for new programmers, but it’s really not all that difficult. Summarizing:
- If a new object has to be created before the copying can occur, the copy constructor is used (note: this includes passing or returning objects by value).
- If a new object does not have to be created before the copying can occur, the assignment operator is used.
Overloading the assignment operator
Overloading the copy assignment operator (operator=) is fairly straightforward, with one specific caveat that we’ll get to. The copy assignment operator must be overloaded as a member function.
This prints:
This should all be pretty straightforward by now. Our overloaded operator= returns *this, so that we can chain multiple assignments together:
Issues due to self-assignment
Here’s where things start to get a little more interesting. C++ allows self-assignment:
This will call f1.operator=(f1), and under the simplistic implementation above, all of the members will be assigned to themselves. In this particular example, the self-assignment causes each member to be assigned to itself, which has no overall impact, other than wasting time. In most cases, a self-assignment doesn’t need to do anything at all!
However, in cases where an assignment operator needs to dynamically assign memory, self-assignment can actually be dangerous:
First, run the program as it is. You’ll see that the program prints “Alex” as it should.
Now run the following program:
You’ll probably get garbage output. What happened?
Consider what happens in the overloaded operator= when the implicit object AND the passed in parameter (str) are both variable alex. In this case, m_data is the same as str.m_data. The first thing that happens is that the function checks to see if the implicit object already has a string. If so, it needs to delete it, so we don’t end up with a memory leak. In this case, m_data is allocated, so the function deletes m_data. But because str is the same as *this, the string that we wanted to copy has been deleted and m_data (and str.m_data) are dangling.
Later on, we allocate new memory to m_data (and str.m_data). So when we subsequently copy the data from str.m_data into m_data, we’re copying garbage, because str.m_data was never initialized.
Detecting and handling self-assignment
Fortunately, we can detect when self-assignment occurs. Here’s an updated implementation of our overloaded operator= for the MyString class:
By checking if the address of our implicit object is the same as the address of the object being passed in as a parameter, we can have our assignment operator just return immediately without doing any other work.
Because this is just a pointer comparison, it should be fast, and does not require operator== to be overloaded.
When not to handle self-assignment
Typically the self-assignment check is skipped for copy constructors. Because the object being copy constructed is newly created, the only case where the newly created object can be equal to the object being copied is when you try to initialize a newly defined object with itself:
In such cases, your compiler should warn you that c is an uninitialized variable.
Second, the self-assignment check may be omitted in classes that can naturally handle self-assignment. Consider this Fraction class assignment operator that has a self-assignment guard:
If the self-assignment guard did not exist, this function would still operate correctly during a self-assignment (because all of the operations done by the function can handle self-assignment properly).
Because self-assignment is a rare event, some prominent C++ gurus recommend omitting the self-assignment guard even in classes that would benefit from it. We do not recommend this, as we believe it’s a better practice to code defensively and then selectively optimize later.
The copy and swap idiom
A better way to handle self-assignment issues is via what’s called the copy and swap idiom. There’s a great writeup of how this idiom works on Stack Overflow .
The implicit copy assignment operator
Unlike other operators, the compiler will provide an implicit public copy assignment operator for your class if you do not provide a user-defined one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).
Just like other constructors and operators, you can prevent assignments from being made by making your copy assignment operator private or using the delete keyword:
Note that if your class has const members, the compiler will instead define the implicit operator= as deleted. This is because const members can’t be assigned, so the compiler will assume your class should not be assignable.
If you want a class with const members to be assignable (for all members that aren’t const), you will need to explicitly overload operator= and manually assign each non-const member.
Copy assignment operator
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.
Explanation
- Typical declaration of a copy assignment operator when copy-and-swap idiom can be used.
- Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used (non-swappable type or degraded performance).
- Forcing a copy assignment operator to be generated by the compiler.
- Avoiding implicit copy assignment.
The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.
Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B & or const volatile B & ;
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M & or const volatile M & .
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.)
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)
The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) exception specification (since C++17)
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
Deleted implicitly-declared copy assignment operator
A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a user-declared move constructor;
- T has a user-declared move assignment operator.
Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of non-class type (or array thereof) that is const ;
- T has a non-static data member of a reference type;
- T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);
- T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.
Trivial copy assignment operator
The copy assignment operator for class T is trivial if all of the following is true:
- it is not user-provided (meaning, it is implicitly-defined or defaulted) , , and if it is defaulted, its signature is the same as implicitly-defined (until C++14) ;
- T has no virtual member functions;
- T has no virtual base classes;
- the copy assignment operator selected for every direct base of T is trivial;
- the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial;
A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.
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.
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
Copy assignment operator
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.
[ edit ] Syntax
[ edit ] explanation.
- Typical declaration of a copy assignment operator when copy-and-swap idiom can be used
- Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used (non-swappable type or degraded performance)
- Forcing a copy assignment operator to be generated by the compiler
- Avoiding implicit copy assignment
The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.
[ edit ] Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B &
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M &
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
[ edit ] Deleted implicitly-declared copy assignment operator
A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a user-declared move constructor
- T has a user-declared move assignment operator
Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of non-class type (or array thereof) that is const
- T has a non-static data member of a reference type.
- T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function)
- T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.
[ edit ] Trivial copy assignment operator
The copy assignment operator for class T is trivial if all of the following is true:
- It is not user-provided (meaning, it is implicitly-defined or defaulted), and if it is defaulted, its signature is the same as implicitly-defined
- T has no virtual member functions
- T has no virtual base classes
- The copy assignment operator selected for every direct base of T is trivial
- The copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial
A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
[ edit ] Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.
[ edit ] Notes
If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either prvalue such as a nameless temporary or xvalue such as the result of std::move ), and selects the copy assignment if the argument is 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 ).
[ edit ] Copy and swap
Copy assignment operator can be expressed in terms of copy constructor, destructor, and the swap() member function, if one is provided:
T & T :: operator = ( T arg ) { // copy/move constructor is called to construct arg swap ( arg ) ; // resources exchanged between *this and arg return * this ; } // destructor is called to release the resources formerly held by *this
For non-throwing swap(), this form provides strong exception guarantee . For rvalue arguments, this form automatically invokes the move constructor, and is sometimes referred to as "unifying assignment operator" (as in, both copy and move). However, this approach is not always advisable due to potentially significant overhead: see assignment operator overloading for details.
[ edit ] Example
The C++ implicit assignment operator is a non-ref-qualified member, even if the base class’s assignment has a ref-qualifier
Consider the following C++ class:
This defines a class for which you can assign to an lvalue reference, but not to an rvalue reference.
Assigning to an rvalue is not generally useful, since the object has no name, and consequently it is difficult to do anything with the assigned-to object afterward.¹
Great, we got rid of assignment to a temporary, which we’ve seen has been a source of confusion .
Now consider this:
We created a derived class and inherited the assignment operator from it. Do you expect the inherited assignment operator to block rvalues?
You probably guessed that the answer is no , seeing as I gave it away in the title.
The reason is that I lied when I said that the assignment operator was inherited. It was not inherited. It was implicitly declared .
The rules for implicit declaration of the copy assignment operator are spelled out in [class.copy.assign] , paragraphs 2 and 4. The short version is that a class is eligible for an implicitly-declared copy assignment operator if its base classes and non-static members all have a copy assignment operator. (Analogous rules apply for the implicitly-declared move assignment operator.)
The catch is that the implicitly-declared copy assignment and move assignment operators are declared as an unqualified assignment operator, regardless of the reference-qualifications of the base classes and members. In our example, we get
The lack of a ref-qualification means that this assignment operator applies equally to lvalues and rvalues.
Our attempt to block rvalue assignment fails to propagate to derived classes!
In order to repair this, each derived class must redeclare its assignment operator as lvalue-only.
Oh, we’ve only started our journey down the rabbit-hole.
At least for now, explicitly declaring a copy assignment operator does not cause the implicitly-declared copy/move constructors to disappear, but the behavior is noted as deprecated in the C++ language specification, with the note that a future version of the language may indeed delete them.
To make sure you don’t run into trouble in the future, you’ll want to declare them explicitly.
Great, we’ve restored the copy and move constructors.
But explicitly declaring any constructors causes us to lose the implicitly-declared default constructor.
We’ll have to bring that back too.
The same exercise applies if we also want to block the move assignment operator to rvalues, but it’s more urgent because an explicit declaration of a move assignment operator does delete both the copy and move constructors even in C++20.
Phew, that was annoying.
¹ I mean, I guess you could do this:
but it seems pointless to go to the effort of asking GetBase to create you a Base object, only to overwrite it with your own. You may as well just create your own temporary.
Or, if you didn’t even mean to create a temporary, just use the original value:
Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.
Discussion is closed. Login to edit/delete existing comments.
> Great, we got rid of assignment to a temporary, which we’ve seen has been a source of confusion.
Being able to do assignment into a temporary can be marginally useful. I can think on one use-case for it : let’s assume we have a matrix of bools whose underlying layout is like vector of bools. Then calling matrix(i, j) will yield a temporary (proxy) object whose assignment will result in mutating the corresponding bit in the matrix buffer.
Well, we all know we should not imitate vector of bools but proxy objects are a thing, especially with the new addition of ranges in the standard. Being able to refine behavior for these cases is especially useful when implementing custom adapters/facades. And not being able to inherit such behavior will most probably be really annoying…
Sometimes C++ seems like … all a big mistake
> Because explicitly declaring an assignment operator causes the implicitly-declared copy/move constructors to disappear.
Are you sure about that? Seems to [work for me]( https://godbolt.org/z/veb97xxrT ). Also, if that were true, then `Derived(Derived const&) = default;` wouldn’t have worked either, as that requires `Base` to have a copy constructor, and you claim that it doesn’t have one.
You’re right. I confused it with the move assignment operator. I’ve revised the article. Thanks.
There are still many instances where `Derived` is not actually derived from `Base`. And there’s still the issue that, in the world where `Derived` wouldn’t have an implicit copy constructor, `Base` wouldn’t have one either, and then `Derived(Derived const&) = default;` would default it as deleted.
A nit: in many examples in the article, `Derived` isn’t actually derived from `Base`.
Adventures in application compatibility: The case of the wild instruction pointer that, upon closer inspection, might not be so wild after all
What does this mean the caller specified wait timed out before the operation completed because a host termination is in queued, stay informed, insert/edit link.
Enter the destination URL
Or link to existing content
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Compiler warning (level 4) C5267
- 2 contributors
definition of implicit copy constructor/assignment operator for ' type ' is deprecated because it has a user-provided assignment operator/copy constructor
The C++ Standard deprecated (but didn't remove) the implicit generation of copy and assignment operators under some conditions. The MSVC compiler still generates the copy and assignment operators under those conditions, but may change its behavior in the future if the standard removes the deprecated behavior. The purpose of this warning is to help future proof your code if the committee decides to remove this functionality.
The relevant sections in the C++ standard are:
- class.copy.ctor paragraph 6 , which says: "If the class definition does not explicitly declare a copy constructor, a nonexplicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defaulted. The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor."
- Annex D D.8 , which says: "The implicit definition of a copy constructor as defaulted is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor. The implicit definition of a copy assignment operator as defaulted is deprecated if the class has a user-declared copy constructor or a user-declared destructor. It's possible that future versions of C++ will specify that these implicit definitions are deleted."
The following code shows warning C5267 when an implicitly generated special function is called but isn't explicitly defined. Both /W4 and /w45267 are required to produce this warning.
To resolve this issue, explicitly define the missing copy constructor or copy assignment operator.
Explicitly Defaulted and Deleted Functions
Was this page helpful?
Additional resources
cppreference.com
Copy assignment operator.
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.
[ edit ] Syntax
[ edit ] explanation.
The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.
[ edit ] Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B & or const volatile B & ;
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M & or const volatile M & .
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.)
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)
The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) noexcept specification (since C++17)
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
[ edit ] Deleted implicitly-declared copy assignment operator
An implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a user-declared move constructor;
- T has a user-declared move assignment operator.
Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of a const-qualified non-class type (or array thereof);
- T has a non-static data member of a reference type;
- T has a non-static data member or a direct base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);
- T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.
[ edit ] Trivial copy assignment operator
The copy assignment operator for class T is trivial if all of the following is true:
- it is not user-provided (meaning, it is implicitly-defined or defaulted);
- T has no virtual member functions;
- T has no virtual base classes;
- the copy assignment operator selected for every direct base of T is trivial;
- the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial.
A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
[ edit ] Eligible copy assignment operator
Triviality of eligible copy assignment operators determines whether the class is a trivially copyable type .
[ edit ] Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used or needed for constant evaluation (since C++14) . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
[ edit ] 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.
[ edit ] Example
[ edit ] defect reports.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
[ edit ] See also
- converting constructor
- copy constructor
- copy elision
- default constructor
- aggregate initialization
- constant initialization
- copy initialization
- default initialization
- direct initialization
- initializer list
- list initialization
- reference initialization
- value initialization
- zero initialization
- move assignment
- move constructor
- Recent changes
- Offline version
- What links here
- Related changes
- Upload file
- Special pages
- Printable version
- Permanent link
- Page information
- In other languages
- This page was last modified on 30 September 2022, at 01:20.
- This page has been accessed 1,200,884 times.
- Privacy policy
- About cppreference.com
- Disclaimers
Copy assignment operator
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . A type with a public copy assignment operator is CopyAssignable .
[ edit ] Syntax
[ edit ] explanation.
- Typical declaration of a copy assignment operator when copy-and-swap idiom can be used
- Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used
- Forcing a copy assignment operator to be generated by the compiler
- Avoiding implicit copy assignment
The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.
[ edit ] Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B &
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M &
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default .
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
[ edit ] Deleted implicitly-declared copy assignment operator
The implicitly-declared or defaulted copy assignment operator for class T is defined as deleted in any of the following is true:
- T has a non-static data member that is const
- T has a non-static data member of a reference type.
- T has a non-static data member that cannot be copy-assigned (has deleted, inaccessible, or ambiguous copy assignment operator)
- T has direct or virtual base class that cannot be copy-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
- T has a user-declared move constructor
- T has a user-declared move assignment operator
[ edit ] Trivial copy assignment operator
The implicitly-declared copy assignment operator for class T is trivial if all of the following is true:
- T has no virtual member functions
- T has no virtual base classes
- The copy assignment operator selected for every direct base of T is trivial
- The copy assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial
A trivial copy assignment operator makes a copy of the object representation as if by std:: memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
[ edit ] Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is not deleted or trivial, it is defined (that is, a function body is generated and compiled) by the compiler. For union types, the implicitly-defined copy assignment copies the object representation (as by std:: memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using, using built-in assignment for the scalars and copy assignment operator for class types.
The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.
[ edit ] Notes
If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either prvalue such as a nameless temporary or xvalue such as the result of std:: move ), and selects the copy assignment if the argument is 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.
[ edit ] Copy and swap
Copy assignment operator can be expressed in terms of copy constructor, destructor, and the swap() member function, if one is provided:
T & T :: operator = ( T arg ) { // copy/move constructor is called to construct arg swap ( arg ) ; // resources exchanged between *this and arg return * this ; } // destructor is called to release the resources formerly held by *this
For non-throwing swap(), this form provides strong exception guarantee . For rvalue arguments, this form automatically invokes the move constructor, and is sometimes referred to as "unifying assignment operator" (as in, both copy and move).
[ edit ] Example
Copy assignment operator
A copy assignment operator of class T is a non-template non-static member function with the name operator= that takes exactly one parameter (that isn't an explicit object parameter ) of type T , T& , const T& , volatile T& , or const volatile T& . For a type to be CopyAssignable , it must have a public copy assignment operator.
Explanation
The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.
Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T& T::operator=(const T&) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B& ;
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M& .
Otherwise the implicitly-declared copy assignment operator is declared as T& T::operator=(T&) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.).
A class can have multiple copy assignment operators, e.g. both T& T::operator=(T&) and T& T::operator=(T) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11) .
The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) noexcept specification (since C++17) .
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
Deleted implicitly-declared copy assignment operator
An implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a user-declared move constructor;
- T has a user-declared move assignment operator.
Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of a const-qualified non-class type (or array thereof);
- T has a non-static data member of a reference type;
- T has a non-static data member or a direct base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function);
- T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.
Trivial copy assignment operator
The copy assignment operator for class T is trivial if all of the following is true:
- it is not user-provided (meaning, it is implicitly-defined or defaulted);
- T has no virtual member functions;
- T has no virtual base classes;
- the copy assignment operator selected for every direct base of T is trivial;
- the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial.
A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
Eligible copy assignment operator
Triviality of eligible copy assignment operators determines whether the class is a trivially copyable type .
Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used or needed for constant evaluation (since C++14) . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
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.
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- converting constructor
- copy constructor
- copy elision
- default constructor
- aggregate initialization
- constant initialization
- copy initialization
- default initialization
- direct initialization
- initializer list
- list initialization
- reference initialization
- value initialization
- zero initialization
- move assignment
- move constructor
© cppreference.com Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0. https://en.cppreference.com/w/cpp/language/as_operator
cppreference.com
Copy assignment operator
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.
[ edit ] Syntax
[ edit ] explanation.
- Typical declaration of a copy assignment operator when copy-and-swap idiom can be used
- Typical declaration of a copy assignment operator when copy-and-swap idiom cannot be used (non-swappable type or degraded performance)
- Forcing a copy assignment operator to be generated by the compiler
- Avoiding implicit copy assignment
The copy assignment operator is called whenever selected by overload resolution , e.g. when an object appears on the left side of an assignment expression.
[ edit ] Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type ( struct , class , or union ), the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B& or const volatile B &
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M& or const volatile M &
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) . (Note that due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument)
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( const T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
[ edit ] Deleted implicitly-declared copy assignment operator
A implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a user-declared move constructor
- T has a user-declared move assignment operator
Otherwise, it is defined as defaulted.
A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
- T has a non-static data member of non-class type (or array thereof) that is const
- T has a non-static data member of a reference type.
- T has a non-static data member or a direct or virtual base class that cannot be copy-assigned (overload resolution for the copy assignment fails, or selects a deleted or inaccessible function)
- T is a union-like class , and has a variant member whose corresponding assignment operator is non-trivial.
[ edit ] Trivial copy assignment operator
The copy assignment operator for class T is trivial if all of the following is true:
- It is not user-provided (meaning, it is implicitly-defined or defaulted), and if it is defaulted, its signature is the same as implicitly-defined
- T has no virtual member functions
- T has no virtual base classes
- The copy assignment operator selected for every direct base of T is trivial
- The copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial
A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
[ edit ] Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types ( class and struct ), the operator performs member-wise copy assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and copy assignment operator for class types.
The generation of the implicitly-defined copy assignment operator is deprecated (since C++11) if T has a user-declared destructor or user-declared copy constructor.
[ edit ] Notes
If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either prvalue such as a nameless temporary or xvalue such as the result of std::move ), and selects the copy assignment if the argument is 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 ).
[ edit ] Copy and swap
Copy assignment operator can be expressed in terms of copy constructor, destructor, and the swap() member function, if one is provided:
T & T :: operator = ( T arg ) { // copy/move constructor is called to construct arg swap ( arg ) ; // resources exchanged between *this and arg return * this ; } // destructor is called to release the resources formerly held by *this
For non-throwing swap(), this form provides strong exception guarantee . For rvalue arguments, this form automatically invokes the move constructor, and is sometimes referred to as "unifying assignment operator" (as in, both copy and move). However, this approach is not always advisable due to potentially significant overhead: see assignment operator overloading for details.
[ edit ] Example
- Recent changes
- Offline version
- What links here
- Related changes
- Upload file
- Special pages
- Printable version
- Permanent link
- Page information
- In other languages
- This page was last modified on 30 November 2015, at 07:24.
- This page has been accessed 110,155 times.
- Privacy policy
- About cppreference.com
- Disclaimers
cppreference.com
Copy assignment operator.
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T , T & , const T & , volatile T & , or const volatile T & . For a type to be CopyAssignable , it must have a public copy assignment operator.
IMAGES
VIDEO
COMMENTS
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. ... the using-declaration is also hidden by the implicit declaration. Implicitly-defined copy assignment operator.
The implicit definition of a copy assignment operator as defaulted is deprecated if the class has a user-declared copy constructor or a user-declared destructor (15.4, 15.8). In a future revision of this International Standard, these implicit definitions could become deleted (11.4). The rationale behind this text is the well-known Rule of three.
return 0; } So you need the assignment operator, because it has different semantics. It is implicitly defined - if possible - because assignment should be defined by default whenever it is possible. Note, that in most cases your assignment operator is actually not implicitly defined. The above code is just one example, but there are many other ...
The implicit copy assignment operator. Unlike other operators, the compiler will provide an implicit public copy assignment operator for your class if you do not provide a user-defined one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).
Forcing a copy assignment operator to be generated by the compiler Avoiding implicit copy assignment The copy assignment operator is called whenever selected by overload resolution, e.g. when an object appears on the left side of an assignment expression. Implicitly-declared copy assignment operator
A class can have multiple copy assignment operators, e.g. both T & T:: operator = (const T &) and T & T:: operator = (T). If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default. (since C++11)
A copy assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter of type T, T &, const T &, volatile T &, or const volatile T &. For a type to be CopyAssignable, it must have a public copy assignment operator.
The rules for implicit declaration of the copy assignment operator are spelled out in [class.copy.assign], paragraphs 2 and 4. The short version is that a class is eligible for an implicitly-declared copy assignment operator if its base classes and non-static members all have a copy assignment operator.
The C++ Standard deprecated (but didn't remove) the implicit generation of copy and assignment operators under some conditions. The MSVC compiler still generates the copy and assignment operators under those conditions, but may change its behavior in the future if the standard removes the deprecated behavior.
The copy assignment operator is called whenever selected by overload resolution, e.g. when an object appears on the left side of an assignment expression. [] Implicitly-declared copy assignment operatoIf no user-defined copy assignment operators are provided for a class type (struct, class, or union), the compiler will always declare one as an inline public member of the class.
The copy assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial. A trivial copy assignment operator makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD types) are trivially copy-assignable.
The copy assignment operator is called whenever selected by overload resolution, e.g. when an object appears on the left side of an assignment expression.. Implicitly-declared copy assignment operator. If no user-defined copy assignment operators are provided for a class type (struct, class, or union), the compiler will always declare one as an inline public member of the class.
Even if some user-defined copy constructors are present, the user may still force the implicit copy constructor declaration with the keyword default. (since C++11) The implicitly-declared ... The implicitly-declared copy constructor for class T is defined as deleted if T declares a move constructor or move assignment operator. (since C++11)
Deleted implicitly-declared copy assignment operator The implicitly-declared or defaulted copy assignment operator for class T is defined as deleted in any of the following is true: T has a non-static data member that is const T has a non-static data member of a reference type.
Rule of five. Because the presence of a user-defined (include =default or = delete declared) destructor, copy-constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator, any class for which move semantics are desirable, has to declare all five special member functions: #include ...
Forcing a copy assignment operator to be generated by the compiler Avoiding implicit copy assignment The copy assignment operator is called whenever selected by overload resolution, e.g. when an object appears on the left side of an assignment expression. Implicitly-declared copy assignment operator
A class can have multiple copy assignment operators, e.g. both T & T:: operator = (const T &) and T & T:: operator = (T). If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default. (since C++11)