This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Move Constructors and Move Assignment Operators (C++)
- 6 minutes to read
- 10 contributors
This topic describes how to write a move constructor and a move assignment operator for a C++ class. A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: && .
This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.
The following procedures describe how to write a move constructor and a move assignment operator for the example C++ class.
To create a move constructor for a C++ class
Define an empty constructor method that takes an rvalue reference to the class type as its parameter, as demonstrated in the following example:
In the move constructor, assign the class data members from the source object to the object that is being constructed:
Assign the data members of the source object to default values. This prevents the destructor from freeing resources (such as memory) multiple times:
To create a move assignment operator for a C++ class
Define an empty assignment operator that takes an rvalue reference to the class type as its parameter and returns a reference to the class type, as demonstrated in the following example:
In the move assignment operator, add a conditional statement that performs no operation if you try to assign the object to itself.
In the conditional statement, free any resources (such as memory) from the object that is being assigned to.
The following example frees the _data member from the object that is being assigned to:
Follow steps 2 and 3 in the first procedure to transfer the data members from the source object to the object that is being constructed:
Return a reference to the current object, as shown in the following example:
Example: Complete move constructor and assignment operator
The following example shows the complete move constructor and move assignment operator for the MemoryBlock class:
Example Use move semantics to improve performance
The following example shows how move semantics can improve the performance of your applications. The example adds two elements to a vector object and then inserts a new element between the two existing elements. The vector class uses move semantics to perform the insertion operation efficiently by moving the elements of the vector instead of copying them.
This example produces the following output:
Before Visual Studio 2010, this example produced the following output:
The version of this example that uses move semantics is more efficient than the version that does not use move semantics because it performs fewer copy, memory allocation, and memory deallocation operations.
Robust Programming
To prevent resource leaks, always free resources (such as memory, file handles, and sockets) in the move assignment operator.
To prevent the unrecoverable destruction of resources, properly handle self-assignment in the move assignment operator.
If you provide both a move constructor and a move assignment operator for your class, you can eliminate redundant code by writing the move constructor to call the move assignment operator. The following example shows a revised version of the move constructor that calls the move assignment operator:
The std::move function converts the lvalue other to an rvalue.
Rvalue Reference Declarator: && std::move
Submit and view feedback for
Additional resources
- Stack Overflow Public questions & answers
- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Talent Build your employer brand
- Advertising Reach developers & technologists worldwide
- About the company
Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Which to use: move assignment operator vs copy assignment operator
I don't seem to get why would you use the move assignment operator :
over, the copy assignment operator :
The move assignment operator takes an r-value reference only e.g.
In the copy assignment operator , other can be constructor using a copy constructor or a move constructor (if other is initialized with an rvalue, it could be move-constructed --if move-constructor defined--).
If it is copy-constructed , we will be doing 1 copy and that copy can't be avoided.
If it is move-constructed then the performance/behavior is identical to the one produced by the first overload.
My questions are:
1- Why would one want to implement the move assignment operator .
2- If other is constructed from an r-value then which assignment operator would the compiler choose to call? And why?
- overload-resolution
- 1) less work, 2) it'd be ambiguous. – Kerrek SB Nov 6, 2014 at 5:20
- So you are saying for 2) the first overload will be called? – Kam Nov 6, 2014 at 5:24
- CLASSA & operator=(CLASSA && other); is a move assignment operator . Not sure how that changes what you are asking about. A copy assignment operator takes either a CLASSA or a const CLASSA& . – Radiodef Nov 6, 2014 at 5:25
- @Kam: No. An ambiguous overload means that overload resolution fails when you try to use the overload, which in turn makes the program ill formed. – Kerrek SB Nov 6, 2014 at 5:27
- The performance/behaviour will not be identical. There will be probably be one less move if you pass by r-value reference. Whether that matters will depend on how expensive it is to move CLASSA . – Chris Drew Nov 6, 2014 at 5:43
2 Answers 2
You are not comparing like-with-like
If you are writing a move-only type like std::unique_ptr then a move assignment operator would be your only choice.
The more typical case is where you have a copyable type in which case I think you have three options.
- T& operator=(T const&)
- T& operator=(T const&) and T& operator=(T&&)
- T& operator=(T) and move
Note that having both the overloads you suggested in one class is not an option as it would be ambiguous.
Option 1 is the traditional C++98 option and will perform fine in most cases. However, if you need to optimize for r-values you could consider Option 2 and add a move assignment operator.
It is tempting to consider Option 3 and pass-by-value and then move which I think is what you are suggesting. In that case you only have to write one assignment operator. It accepts l-values and at the cost of only one extra move accepts r-values and many people will advocate this approach.
However, Herb Sutter pointed out in his "Back to the Basics! Essentials of Modern C++ Style" talk at CppCon 2014 that this option is problematic and can be much slower. In the case of l-values it will perform an unconditional copy and will not reuse any existing capacity. He provides numbers to backup his claims. The only exception is constructors where there is no existing capacity to reuse and you often have many parameters so pass by-value can reduce the number of overloads needed.
So I would suggest you start with Option 1 and move to Option 2 if you need to optimize for r-values.

Clearly, the two overloads are not equivalent:
- The assignment operator taking an rvalue reference only works with rvalues are on the right-hand side of the expression. To also support lvalues, another overload, e.g., using T const& would be needed for copyable types. Of course, for move-only types, like std::unique_ptr<T> , defining this assignment operator is the appropriate choice.
- The assignment operator taking a value covers both rvalue and lvalue assignments assuming the type in question is both copy- and move-constructible. Its canonical implementation is to call swap() to replace the object's state with the state from the right-hand side. It has the advantage that the copy/move construction of the argument can often be elided.
In any case, you wouldn't want to have both overloads in one class! When assigning from an lvalue, obviously, the version taking a value would be chosen (the other option isn't viable). However, both assignment operators are viable when assigning an rvalue, i.e., there would be an ambiguity. This can easily be verified by trying to compile this code:
To deal with a move- and copy construction separately you could define a pair of assignment operators using T&& and T const& as arguments. However, this results in having to implement two versions of essentially the same copy assignment while having just a T as argument requires just one copy assignment to be implemented.
Thus, there are two obvious choices:
- For a move-only type you'd define T::operator= (T&&) .
- For a copyable type you'd define T::operator=(T) .
- 2 Herb sutter points out that using pass by-value in this way can be much slower than pass by reference-to-const due to making an unconditional copy and not reusing existing capacity. – Chris Drew Nov 6, 2014 at 7:20
Your Answer
Sign up or log in, post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service , privacy policy and cookie policy
Not the answer you're looking for? Browse other questions tagged c++ c++11 overload-resolution or ask your own question .
- The Overflow Blog
- How Intuit democratizes AI development across teams through reusability sponsored post
- The nature of simulating nature: A Q&A with IBM Quantum researcher Dr. Jamie...
- Featured on Meta
- We've added a "Necessary cookies only" option to the cookie consent popup
- The [amazon] tag is being burninated
- Launching the CI/CD and R Collectives and community editing features for...
- Staging Ground Beta 1 Recap, and Reviewers needed for Beta 2
- Temporary policy: ChatGPT is banned
Hot Network Questions
- Lots of pick movement
- Largest Binary Area
- What sort of strategies would a medieval military use against a fantasy giant?
- Transgenic Peach DNA Splicing
- Can the Spiritual Weapon spell be used as cover?
- Jordan's line about intimate parties in The Great Gatsby?
- Mini project #2: Guessing a number loop
- How does fire heat air?
- Can I tell police to wait and call a lawyer when served with a search warrant?
- How can I find out which sectors are used by files on NTFS?
- What can a lawyer do if the client wants him to be acquitted of everything despite serious evidence?
- Experiment to crush soda can by air pressure
- Prevent requests to 127.0.0.1 from being forwarded to http_proxy
- Applications of super-mathematics to non-super mathematics
- "Users & Groups" does not display groups on Ventura 13.2
- Minimising the environmental effects of my dyson brain
- Follow Up: struct sockaddr storage initialization by network format-string
- Do you really get double penalized for rolling HSA excess contributions to the next year?
- Short story taking place on a toroidal planet or moon involving flying
- Wahoo Kickr with 8 speed cassette?
- How to insulate the neutral from the ground in a Subpanel Siemens mc1020b1100sz
- A limit involving the quotient of two sums
- Chord III is rarely used, but Pachelbel's Canon in D has F#m
- OK to delete Windows.db file on PC?
Your privacy
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .
cppreference.com
Operator overloading.
Customizes the C++ operators for operands of user-defined types.
[ edit ] Syntax
Overloaded operators are functions with special function names:

[ edit ] Overloaded operators
When an operator appears in an expression , and at least one of its operands has a class type or an enumeration type , then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following:
Note: for overloading co_await , (since C++20) user-defined conversion functions , user-defined literals , allocation and deallocation see their respective articles.
Overloaded operators (but not the built-in operators) can be called using function notation:
[ edit ] Restrictions
- The operators :: (scope resolution), . (member access), .* (member access through pointer to member), and ?: (ternary conditional) cannot be overloaded.
- New operators such as ** , <> , or &| cannot be created.
- It is not possible to change the precedence, grouping, or number of operands of operators.
- The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.
- The overloads of operators && and || lose short-circuit evaluation.
[ edit ] Canonical implementations
Besides the restrictions above, the language puts no other constraints on what the overloaded operators do, or on the return type (it does not participate in overload resolution), but in general, overloaded operators are expected to behave as similar as possible to the built-in operators: operator + is expected to add, rather than multiply its arguments, operator = is expected to assign, etc. The related operators are expected to behave similarly ( operator + and operator + = do the same addition-like operation). The return types are limited by the expressions in which the operator is expected to be used: for example, assignment operators return by reference to make it possible to write a = b = c = d , because the built-in operators allow that.
Commonly overloaded operators have the following typical, canonical forms: [1]
[ edit ] Assignment operator
The assignment operator ( operator = ) has special properties: see copy assignment and move assignment for details.
The canonical copy-assignment operator is expected to perform no action on self-assignment , and to return the lhs by reference:
In those situations where copy assignment cannot benefit from resource reuse (it does not manage a heap-allocated array and does not have a (possibly transitive) member that does, such as a member std::vector or std::string ), there is a popular convenient shorthand: the copy-and-swap assignment operator, which takes its parameter by value (thus working as both copy- and move-assignment depending on the value category of the argument), swaps with the parameter, and lets the destructor clean it up.
This form automatically provides strong exception guarantee , but prohibits resource reuse.
[ edit ] Stream extraction and insertion
The overloads of operator>> and operator<< that take a std:: istream & or std:: ostream & as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument ( b in a @ b ), they must be implemented as non-members.
These operators are sometimes implemented as friend functions .
[ edit ] Function call operator
When a user-defined class overloads the function call operator, operator ( ) , it becomes a FunctionObject type.
An object of such a type can be used in a function call expression:
Many standard algorithms, from std:: sort to std:: accumulate accept FunctionObject s to customize behavior. There are no particularly notable canonical forms of operator ( ) , but to illustrate the usage:
[ edit ] Increment and decrement
When the postfix increment or decrement operator appears in an expression, the corresponding user-defined function ( operator ++ or operator -- ) is called with an integer argument 0 . Typically, it is implemented as T operator ++ ( int ) or T operator -- ( int ) , where the argument is ignored. The postfix increment and decrement operators are usually implemented in terms of the prefix versions:
Although the canonical implementations of the prefix increment and decrement operators return by reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std::atomic return by value.
[ edit ] Binary arithmetic operators
Binary operators are typically implemented as non-members to maintain symmetry (for example, when adding a complex number and an integer, if operator+ is a member function of the complex type, then only complex + integer would compile, and not integer + complex ). Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments:
[ edit ] Comparison operators
Standard algorithms such as std:: sort and containers such as std:: set expect operator < to be defined, by default, for the user-provided types, and expect it to implement strict weak ordering (thus satisfying the Compare requirements). An idiomatic way to implement strict weak ordering for a structure is to use lexicographical comparison provided by std::tie :
Typically, once operator < is provided, the other relational operators are implemented in terms of operator < .
Likewise, the inequality operator is typically implemented in terms of operator == :
When three-way comparison (such as std::memcmp or std::string::compare ) is provided, all six two-way comparison operators may be expressed through that:
[ edit ] Array subscript operator
User-defined classes that provide array-like access that allows both reading and writing typically define two overloads for operator [ ] : const and non-const variants:
If the value type is known to be a scalar type, the const variant should return by value.
Where direct access to the elements of the container is not wanted or not possible or distinguishing between lvalue c [ i ] = v ; and rvalue v = c [ i ] ; usage, operator [ ] may return a proxy. See for example std::bitset::operator[] .
Because a subscript operator can only take one subscript until C++23, to provide multidimensional array access semantics, e.g. to implement a 3D array access a [ i ] [ j ] [ k ] = x ; , operator [ ] has to return a reference to a 2D plane, which has to have its own operator [ ] which returns a reference to a 1D row, which has to have operator [ ] which returns a reference to the element. To avoid this complexity, some libraries opt for overloading operator ( ) instead, so that 3D access expressions have the Fortran-like syntax a ( i, j, k ) = x ; .
[ edit ] Bitwise arithmetic operators
User-defined classes and enumerations that implement the requirements of BitmaskType are required to overload the bitwise arithmetic operators operator & , operator | , operator ^ , operator~ , operator & = , operator | = , and operator ^ = , and may optionally overload the shift operators operator << operator >> , operator >>= , and operator <<= . The canonical implementations usually follow the pattern for binary arithmetic operators described above.
[ edit ] Boolean negation operator
[ edit ] rarely overloaded operators.
The following operators are rarely overloaded:
- The address-of operator, operator & . If the unary & is applied to an lvalue of incomplete type and the complete type declares an overloaded operator & , it is unspecified whether the operator has the built-in meaning or the operator function is called. Because this operator may be overloaded, generic libraries use std::addressof to obtain addresses of objects of user-defined types. The best known example of a canonical overloaded operator& is the Microsoft class CComPtrBase . An example of this operator's use in EDSL can be found in boost.spirit .
- The boolean logic operators, operator && and operator || . Unlike the built-in versions, the overloads cannot implement short-circuit evaluation. Also unlike the built-in versions, they do not sequence their left operand before the right one. (until C++17) In the standard library, these operators are only overloaded for std::valarray .
- The comma operator, operator, . Unlike the built-in version, the overloads do not sequence their left operand before the right one. (until C++17) Because this operator may be overloaded, generic libraries use expressions such as a, void ( ) ,b instead of a,b to sequence execution of expressions of user-defined types. The boost library uses operator, in boost.assign , boost.spirit , and other libraries. The database access library SOCI also overloads operator, .
- The member access through pointer to member operator - > * . There are no specific downsides to overloading this operator, but it is rarely used in practice. It was suggested that it could be part of a smart pointer interface , and in fact is used in that capacity by actors in boost.phoenix . It is more common in EDSLs such as cpp.react .
[ edit ] Notes
[ edit ] example, [ edit ] defect reports.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
[ edit ] See also
- Operator precedence
- Alternative operator syntax
- Argument-dependent lookup
[ edit ] External links
- 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 19 February 2023, at 14:52.
- This page has been accessed 4,819,630 times.
- Privacy policy
- About cppreference.com
- Disclaimers


IMAGES
VIDEO
COMMENTS
The move assignment operator as defined by the Microsoft page does more work than the move constructor: it is protected against self-assignment. The move constructor is not protected against that. But: as I already said, the constructor will be inlined in almost all cases.
To create a move assignment operator for a C++ class Define an empty assignment operator that takes an rvalue reference to the class type as its parameter and returns a reference to the class type, as demonstrated in the following example: C++ Copy MemoryBlock& operator= (MemoryBlock&& other) { }
The move assignment operator takes an r-value reference only e.g. CLASSA a1, a2, a3; a1 = a2 + a3; In the copy assignment operator, other can be constructor using a copy constructor or a move constructor (if other is initialized with an rvalue, it could be move-constructed --if move-constructor defined--).
Assignment operator The assignment operator ( operator=) has special properties: see copy assignment and move assignment for details. The canonical copy-assignment operator is expected to perform no action on self-assignment, and to return the lhs by reference: