Move assignment operator
A move 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 && , const T && , volatile T && , or const volatile T && .
Explanation
- Typical declaration of a move assignment operator.
- Forcing a move assignment operator to be generated by the compiler.
- Avoiding implicit move assignment.
The move assignment operator is called whenever it is selected by overload resolution , e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector may result in the argument being left empty. This is not, however, a guarantee. A move assignment is less, not more restrictively defined than ordinary assignment; where ordinary assignment must leave two copies of data at completion, move assignment is required to leave only one.
Implicitly-declared move assignment operator
If no user-defined move assignment operators are provided for a class type ( struct , class , or union ), and all of the following is true:
- there are no user-declared copy constructors;
- there are no user-declared move constructors;
- there are no user-declared copy assignment operators;
- there are no user-declared destructors;
then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator=(T&&) .
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 .
The implicitly-declared (or defaulted on its first declaration) move assignment operator has an exception specification as described in dynamic exception specification (until C++17) exception specification (since C++17)
Because some assignment operator (move or copy) 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 move assignment operator
The implicitly-declared or defaulted move assignment operator for class T is defined as deleted if 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 move-assigned (has deleted, inaccessible, or ambiguous move assignment operator);
- T has direct or virtual base class that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator);
Trivial move assignment operator
The move 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 move assignment operator selected for every direct base of T is trivial;
- the move assignment operator selected for every non-static class type (or array of class type) member of T is trivial;
A trivial move assignment operator performs the same action as the trivial copy assignment operator, that is, makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially move-assignable.
Implicitly-defined move assignment operator
If the implicitly-declared move 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 move assignment operator copies the object representation (as by std::memmove ).
For non-union class types ( class and struct ), the move assignment operator performs full member-wise move assignment of the object's direct bases and immediate non-static members, in their declaration order, using built-in assignment for the scalars, memberwise move-assignment for arrays, and move assignment operator for class types (called non-virtually).
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.
Move assignment operator
A move 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 && , const T && , volatile T && , or const volatile T && . A type with a public move assignment operator is MoveAssignable .
[ edit ] Syntax
[ edit ] explanation.
- Typical declaration of a move assignment operator
- Forcing a move assignment operator to be generated by the compiler
- Avoiding implicit move assignment
The move assignment operator is called whenever it is selected by overload resolution , e.g. when an object appears on the left side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std:: string or from a std:: vector leaves the right-hand side argument empty.
[ edit ] Implicitly-declared move assignment operator
If no user-defined move assignment operators are provided for a class type ( struct , class , or union ), and all of the following is true:
- there are no user-declared copy constructors
- there are no user-declared move constructors
- there are no user-declared copy assignment operators
- there are no user-declared destructors
- the implicitly-declared move assignment operator would not be defined as deleted
then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator= T(T&&)
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 .
Because some assignment operator (move or copy) 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 move assignment operator
The implicitly-declared or defaulted move 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 move-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
- T has direct or virtual base class that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
- T has a non-static data member or a direct or virtual base without a move assignment operator that is not trivially copyable.
- T has a direct or indirect virtual base class
[ edit ] Trivial move assignment operator
The implicitly-declared move 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 move assignment operator selected for every direct base of T is trivial
- The move assignment operator selected for every non-static class type (or array of class type) memeber of T is trivial
A trivial move assignment operator performs the same action as the trivial copy assignment operator, that is, makes a copy of the object representation as if by std:: memmove . All data types compatible with the C language (POD types) are trivially move-assignable.
[ edit ] Implicitly-defined move assignment operator
If the implicitly-declared move 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 move assignment operator copies the object representation (as by std:: memmove ). For non-union class types ( class and struct ), the move assignment operator performs full member-wise move assignment of the object's bases and non-static members, in their initialization order, using built-in assignment for the scalars and move 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 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.
The copy-and-swap assignment operator
T & T :: operator = ( T arg ) { swap ( arg ) ; return * this ; }
performs an equivalent of move assignment for rvalue arguments at the cost of one additional call to the move constructor of T, which is often acceptable.
[ edit ] Example
Move assignment operator
A move 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 && , const T && , volatile T && , or const volatile T && .
[ edit ] Syntax
[ edit ] explanation.
- Typical declaration of a move assignment operator
- Forcing a move assignment operator to be generated by the compiler
- Avoiding implicit move assignment
The move assignment operator is called whenever it is selected by overload resolution , e.g. when an object appears on the left side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector leaves the right-hand side argument empty.
[ edit ] Implicitly-declared move assignment operator
If no user-defined move assignment operators are provided for a class type ( struct , class , or union ), and all of the following is true:
- there are no user-declared copy constructors
- there are no user-declared move constructors
- there are no user-declared copy assignment operators
- there are no user-declared destructors
- (until C++14) the implicitly-declared move assignment operator would not be defined as deleted
then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator=(T&&) .
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 .
Because some assignment operator (move or copy) 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 move assignment operator
The implicitly-declared or defaulted move 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 move-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
- T has direct or virtual base class that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator)
- (until C++14) T has a non-static data member or a direct or virtual base without a move assignment operator that is not trivially copyable.
- (until C++14) T has a direct or indirect virtual base class
(since C++14) A deleted implicitly-declared move assignment operator is ignored by overload resolution
[ edit ] Trivial move assignment operator
The move 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 move assignment operator selected for every direct base of T is trivial
- The move assignment operator selected for every non-static class type (or array of class type) member of T is trivial
A trivial move assignment operator performs the same action as the trivial copy assignment operator, that is, makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially move-assignable.
[ edit ] Implicitly-defined move assignment operator
If the implicitly-declared move 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 move assignment operator copies the object representation (as by std::memmove ).
For non-union class types ( class and struct ), the move assignment operator performs full member-wise move assignment of the object's direct bases and immediate non-static members, in their declaration order, using built-in assignment for the scalars, memberwise move-assignment for arrays, and move assignment operator for class types (called non-virtually).
[ 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.
The copy-and-swap assignment operator
performs an equivalent of move assignment for rvalue arguments at the cost of one additional call to the move constructor of T, which is often acceptable. See assignment operator overloading for further detail on the use and trade-offs.
[ edit ] Example
- Standard Template Library
- STL Priority Queue
- STL Interview Questions
- STL Cheatsheet
- C++ Templates
- C++ Functors
- C++ Iterators
std::move in Utility in C++ | Move Semantics, Move Constructors and Move Assignment Operators
Prerequisites:
- lvalue reference
- rvalue reference
- Copy Semantics (Copy Constructor)
References:
In C++ there are two types of references-
- An lvalue is an expression that will appear on the left-hand side or on the right-hand side of an assignment.
- Simply, a variable or object that has a name and memory address.
- It uses one ampersand (&).
- An rvalue is an expression that will appear only on the right-hand side of an assignment.
- A variable or object has only a memory address (temporary objects).
- It uses two ampersands (&&).
Move Constructor And Semantics:
The move constructor was introduced in C++11 . The need or purpose of a move constructor is to steal or move as many resources as it can from the source (original) object , as fast as possible, because the source does not need to have a meaningful value anymore, and/or because it is going to be destroyed in a moment anyway. So that one can avoid unnecessarily creating copies of an object and make efficient use of the resources
While one can steal the resources, but one must leave the source (original) object in a valid state where it can be correctly destroyed.
Move constructors typically “steal” the resource of the source (original) object rather than making several copies of them, and leaves the source object in a “valid but unspecified state”.
The copy constructor uses the lvalue references which are marked with one ampersand (&) while the move constructor uses the rvalue references are marked with two ampersands (&&).
std::move() is a function used to convert an lvalue reference into the rvalue reference. Used to move the resources from a source object i.e. for efficient transfer of resources from one object to another. std::move() is defined in the <utility> header .
template< class T > typename std::remove_reference<T>::type&& move(T&& t) noexcept; (since C++11)(until C++14) template< class T > constexpr std::remove_reference_t<T>&& move(T&& t) noexcept (since C++14)
Example: Below is the C++ program to show what happens without using move semantics i.e. before C++11.
Explanation:
Assuming the program is compiled and executed using a compiler that doesn’t support move semantics. In the main() function,
1. std::vector<std::string> vecString;- An empty vector is created with no elements in it. 2. vecString = createAndInsert();- The createAndInsert() function is called. 3. In createAndInsert() function-
- std::vector<std::string> vec;- Another new empty vector named as vec is created.
- vec.reserve(3);- Reserving the size of 3 elements.
- std::string str(“Hello”);- A string named as str initialized with a “Hello”.
- vec.push_back( str );- A string is passed by value into the vector vec. Therefore a (deep) copy of str will be created and inserted into the vec by calling a copy constructor of the String class.
- A temporary object will be created (str + str) with its own separate memory.
- This temporary object is inserted into vector vec which is passed by value again means that a (deep) copy of the temporary string object will be created.
- As of now, the temporary object is no longer needed hence it will be destroyed.
Note: Here, we unnecessarily allocate & deallocate the memory of the temporary string object. which can be optimized (improved) further just by moving the data from the source object.
- vec.push_back( str );- The same process as of Line no. 5 will be carried out. Remember at this point the str string object will be last used.
- Firstly, the string object str will be destroyed because the scope is left where it is declared.
- Secondly, a local vector of string i.e vec is returned. As the return type of the function is not by a reference. Hence, a deep copy of the whole vector will be created by allocating at a separate memory location and then destroys the local vec object because the scope is left where it is declared.
- Finally, the copy of the vector of strings will be returned to the caller main() function.
- At the last, after returning to the caller main() function, simply printing the elements of the local vecString vector.
Example: Below is the C++ program to implement the above concept using move semantics i.e. since C++11 and later.
Here, in order to use the move semantics. The compiler must support the C++11 standards or above. The story of execution for the main() function and createAndInsert() function remains the same till the line vec.push_back( str );
A question may arise why the temporary object is not moved to vector vec using std::move(). The reason behind it is the push_back() method of the vector. Since C++11 the push_back() method has been provided with its new overloaded version.
The push_back() method takes its parameter by const reference, but since std::vector stores its elements by value, a deep copy of str is created and inserted into the vector. This involves calling the copy constructor of std::string.
Syntax:
constexpr void push_back(const T& value); (since C++20) void push_back(T&& value); (since C++11) (until C++20) void push_back(const T& value); (until C++20) constexpr void push_back(T&& value); (since C++20)
- A temporary object str + str is created.
- This temporary object is then passed to vec.push_back(). Since std::vector stores elements by value, it will create a copy of this temporary object.
- The temporary object is destroyed as it is no longer needed.
- vec.push_back(std::move(str));-
- std::move() casts str to an rvalue reference, and push_back() will move the contents of str into the vector, leaving str in a valid but unspecified state.
- return vec; – This typically involves returning the local vector vec. While a deep copy of the vector would normally be created, modern compilers often use Return Value Optimization (RVO) to eliminate unnecessary copying.
A question may arise while returning the vec object to its caller. As it is not required anymore and also a whole temporary object of a vector is going to be created and also local vector vec will be destroyed, then why std::move() is not used to steal the value and return it. Its answer is simple and obvious, there is optimization at the compiler level known as (Named) Return Value Object, more popularly known as RVO .
Some Fallback Of Move Semantics:
- It doesn’t make any sense to steal or move the resources of a const object.
- See constObjectCallFunc() function in the below program
- See baz() function in the below program
- See bar() function in the below program
Note: The foo() function have all necessary types of arguments.
Below is the C++ program to implement all the above concepts-
Summary:
- Move semantics allows us to optimize the copying of objects, where we do not need the worth. It is often used implicitly (for unnamed temporary objects or local return values) or explicitly with std::move().
- std::move() means “no longer need this value” .
- An object marked with std::move() is never partially destroyed. i.e. The destructor will be called to destroy the object properly.
Similar Reads
- Blogathon-2021
- cpp-constructor
- cpp-memory-management
Improve your Coding Skills with Practice
What kind of Experience do you want to share?
Move assignment operator
A move assignment operator of class T is a non-template non-static member function with the name operator = that takes exactly one parameter (that is not an explicit object parameter ) (since C++23) of type T && , const T && , volatile T && , or const volatile T && .
Explanation
The move assignment operator is called whenever it is selected by overload resolution , e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.
Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.), rather than make copies of them, and leave the argument in some valid but otherwise indeterminate state. For example, move-assigning from a std::string or from a std::vector may result in the argument being left empty. This is not, however, a guarantee. A move assignment is less, not more restrictively defined than ordinary assignment; where ordinary assignment must leave two copies of data at completion, move assignment is required to leave only one.
Implicitly-declared move assignment operator
If no user-defined move assignment operators are provided for a class type, and all of the following is true:
- there are no user-declared copy constructors ;
- there are no user-declared move constructors ;
- there are no user-declared copy assignment operators ;
- there is no user-declared destructor ,
then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator=(T&&) .
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 .
The implicitly-declared (or defaulted on its first declaration) move assignment operator has an exception specification as described in dynamic exception specification (until C++17) noexcept specification (since C++17) .
Because some assignment operator (move or copy) 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 move assignment operator
The implicitly-declared or defaulted move assignment operator for class T is defined as deleted if 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 or a direct base class that cannot be move-assigned (has deleted, inaccessible, or ambiguous move assignment operator).
A deleted implicitly-declared move assignment operator is ignored by overload resolution .
Trivial move assignment operator
The move 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 move assignment operator selected for every direct base of T is trivial;
- the move assignment operator selected for every non-static class type (or array of class type) member of T is trivial.
A trivial move assignment operator performs the same action as the trivial copy assignment operator, that is, makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially move-assignable.
Eligible move assignment operator
Triviality of eligible move assignment operators determines whether the class is a trivially copyable type .
Implicitly-defined move assignment operator
If the implicitly-declared move 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 move assignment operator copies the object representation (as by std::memmove ).
For non-union class types, the move assignment operator performs full member-wise move assignment of the object's direct bases and immediate non-static members, in their declaration order, using built-in assignment for the scalars, memberwise move-assignment for arrays, and move assignment operator for class types (called non-virtually).
As with copy assignment, 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:
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.
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
- constructor
- converting constructor
- copy assignment
- copy constructor
- default constructor
- aggregate initialization
- constant initialization
- copy initialization
- default initialization
- direct initialization
- list initialization
- reference initialization
- value initialization
- zero initialization
- move constructor
© cppreference.com Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0. https://en.cppreference.com/w/cpp/language/move_operator
cppreference.com
Assignment operators.
Assignment operators modify the value of the object.
[ edit ] Definitions
Copy assignment replaces the contents of the object a with a copy of the contents of b ( b is not modified). For class types, this is performed in a special member function, described in copy assignment operator .
For non-class types, copy and move assignment are indistinguishable and are referred to as direct assignment .
Compound assignment replace the contents of the object a with the result of a binary operation between the previous value of a and the value of b .
[ edit ] Assignment operator syntax
The assignment expressions have the form
- ↑ target-expr must have higher precedence than an assignment expression.
- ↑ new-value cannot be a comma expression, because its precedence is lower.
[ edit ] Built-in simple assignment operator
For the built-in simple assignment, the object referred to by target-expr is modified by replacing its value with the result of new-value . target-expr must be a modifiable lvalue.
The result of a built-in simple assignment is an lvalue of the type of target-expr , referring to target-expr . If target-expr is a bit-field , the result is also a bit-field.
[ edit ] Assignment from an expression
If new-value is an expression, it is implicitly converted to the cv-unqualified type of target-expr . When target-expr is a bit-field that cannot represent the value of the expression, the resulting value of the bit-field is implementation-defined.
If target-expr and new-value identify overlapping objects, the behavior is undefined (unless the overlap is exact and the type is the same).
In overload resolution against user-defined operators , for every type T , the following function signatures participate in overload resolution:
For every enumeration or pointer to member type T , optionally volatile-qualified, the following function signature participates in overload resolution:
For every pair A1 and A2 , where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signature participates in overload resolution:
[ edit ] Built-in compound assignment operator
The behavior of every built-in compound-assignment expression target-expr op = new-value is exactly the same as the behavior of the expression target-expr = target-expr op new-value , except that target-expr is evaluated only once.
The requirements on target-expr and new-value of built-in simple assignment operators also apply. Furthermore:
- For + = and - = , the type of target-expr must be an arithmetic type or a pointer to a (possibly cv-qualified) completely-defined object type .
- For all other compound assignment operators, the type of target-expr must be an arithmetic type.
In overload resolution against user-defined operators , for every pair A1 and A2 , where A1 is an arithmetic type (optionally volatile-qualified) and A2 is a promoted arithmetic type, the following function signatures participate in overload resolution:
For every pair I1 and I2 , where I1 is an integral type (optionally volatile-qualified) and I2 is a promoted integral type, the following function signatures participate in overload resolution:
For every optionally cv-qualified object type T , the following function signatures participate in overload resolution:
[ edit ] Example
Possible output:
[ edit ] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
[ edit ] See also
Operator precedence
Operator overloading
- 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 25 January 2024, at 23:41.
- Privacy policy
- About cppreference.com
- Disclaimers
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Copy constructors and copy assignment operators (C++)
- 8 contributors
Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment . In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++) .
Both the assignment operation and the initialization operation cause objects to be copied.
Assignment : When one object's value is assigned to another object, the first object is copied to the second object. So, this code copies the value of b into a :
Initialization : Initialization occurs when you declare a new object, when you pass function arguments by value, or when you return by value from a function.
You can define the semantics of "copy" for objects of class type. For example, consider this code:
The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make b a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows:
Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x); .
Use the copy constructor.
If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you. Similarly, if you don't declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor doesn't suppress the compiler-generated copy assignment operator, and vice-versa. If you implement either one, we recommend that you implement the other one, too. When you implement both, the meaning of the code is clear.
The copy constructor takes an argument of type ClassName& , where ClassName is the name of the class. For example:
Make the type of the copy constructor's argument const ClassName& whenever possible. This prevents the copy constructor from accidentally changing the copied object. It also lets you copy from const objects.
Compiler generated copy constructors
Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name ." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name & . In such a case, the compiler-generated copy constructor's argument is also const .
When the argument type to the copy constructor isn't const , initialization by copying a const object generates an error. The reverse isn't true: If the argument is const , you can initialize by copying an object that's not const .
Compiler-generated assignment operators follow the same pattern for const . They take a single argument of type ClassName& unless the assignment operators in all base and member classes take arguments of type const ClassName& . In this case, the generated assignment operator for the class takes a const argument.
When virtual base classes are initialized by copy constructors, whether compiler-generated or user-defined, they're initialized only once: at the point when they are constructed.
The implications are similar to the copy constructor. When the argument type isn't const , assignment from a const object generates an error. The reverse isn't true: If a const value is assigned to a value that's not const , the assignment succeeds.
For more information about overloaded assignment operators, see Assignment .
Was this page helpful?
IMAGES
COMMENTS
Learn how to declare, define, and use a move assignment operator in C++, a non-template non-static member function that can transfer the resources of an argument. See syntax, examples, and requirements for implicit and explicit move assignment operators.
Declaring copy constructor or assignment or destructor prevents default move constructor generation. If we define any of these functions,we have to define move constructor. But how about the case copy constructor is defined but move constructor is created by default keyword.Does it work as expected? -
Learn how to declare and use move constructors in C++, which can transfer resources from an argument to a new object without copying them. See the syntax, explanation, examples and implicitly-declared move constructors.
Learn how to write a move constructor and a move assignment operator for a C++ class that manages a memory buffer. See the difference between copying and moving resources, and how to prevent resource leaks and self-assignment.
Learn how to use the move assignment operator in C++ 11 to handle objects more efficiently, especially when managing resources like memory. See examples of user-defined move assignment operators, move constructors, and std::move function.
Learn how to use move constructors in C++ to create new objects from existing ones without copying them. See examples, syntax, noexcept keyword and comparison with copy constructors.
then the compiler will declare a move assignment operator as an inline public member of its class with the signature T& T::operator=(T&&).. 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 ...
Learn how to define and use a move assignment operator in C++, which is a non-template non-static member function that takes one parameter of type T&&. See syntax, explanation, examples, and notes on implicit and deleted move assignment operators.
@Rob: The definition of the default copy assignment operator starting at 12.8:10 makes no mention of a throw clause. This makes sense to me, since a default copy assignment operator can call a non-default assignment, which could throw. In the specific example given in the question obviously std::string::operator=(const std::string&) can throw.
Learn how to declare, define, and use a copy assignment operator in C++, a non-template non-static member function that copies the content of an object without mutating it. See the syntax, rules, and examples of the copy assignment operator, and how to explicitly default or delete it.
Forcing a move assignment operator to be generated by the compiler Avoiding implicit move assignment The move assignment operator is called whenever it is selected by overload resolution , e.g. when an object appears on the left side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.
Learn how to use move semantics, move constructors and std::move utility in C++ to efficiently transfer resources from one object to another. See examples, syntax and explanations of copy semantics, lvalue and rvalue references, and move assignment operators.
The move assignment operator is called whenever it is selected by overload resolution, e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.. Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors ...
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.
Learn how to use assignment operators in C++, including simple, compound, and user-defined operators. Find out the rules and requirements for target-expr and new-value, and the differences between built-in and user-defined operators.
Learn how to define and use copy constructors and assignment operators for class types in C++. See examples, compiler-generated copy constructors, and the difference between copy and move assignment.
The default move-assignment for built-in types is a copy, this includes pointers. If you use a defaulted move-assignment operator on a class with a raw pointer you will end up with two pointers to the same object. So, you should write your own non-defaulted move-assignment operator if your class contains raw pointers that manage resources.
While I was making myself familliar with C++14 specification, I have read that, if a class has no explicitly declared Copy Constructor, Copy Assignment Operator, Move Constructor nor Move Assignment Operator, default implementations should be generated by the compiler. Consider this empty class for thread safe files: