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++)
- 9 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
Was this page helpful?
Additional resources
22.3 — Move constructors and move assignment
In lesson 22.1 -- Introduction to smart pointers and move semantics , we took a look at std::auto_ptr, discussed the desire for move semantics, and took a look at some of the downsides that occur when functions designed for copy semantics (copy constructors and copy assignment operators) are redefined to implement move semantics.
In this lesson, we’ll take a deeper look at how C++11 resolves these problems via move constructors and move assignment.
Recapping copy constructors and copy assignment
First, let’s take a moment to recap copy semantics.
Copy constructors are used to initialize a class by making a copy of an object of the same class. Copy assignment is used to copy one class object to another existing class object. By default, C++ will provide a copy constructor and copy assignment operator if one is not explicitly provided. These compiler-provided functions do shallow copies, which may cause problems for classes that allocate dynamic memory. So classes that deal with dynamic memory should override these functions to do deep copies.
Returning back to our Auto_ptr smart pointer class example from the first lesson in this chapter, let’s look at a version that implements a copy constructor and copy assignment operator that do deep copies, and a sample program that exercises them:
In this program, we’re using a function named generateResource() to create a smart pointer encapsulated resource, which is then passed back to function main(). Function main() then assigns that to an existing Auto_ptr3 object.
When this program is run, it prints:
(Note: You may only get 4 outputs if your compiler elides the return value from function generateResource())
That’s a lot of resource creation and destruction going on for such a simple program! What’s going on here?
Let’s take a closer look. There are 6 key steps that happen in this program (one for each printed message):
- Inside generateResource(), local variable res is created and initialized with a dynamically allocated Resource, which causes the first “Resource acquired”.
- Res is returned back to main() by value. We return by value here because res is a local variable -- it can’t be returned by address or reference because res will be destroyed when generateResource() ends. So res is copy constructed into a temporary object. Since our copy constructor does a deep copy, a new Resource is allocated here, which causes the second “Resource acquired”.
- Res goes out of scope, destroying the originally created Resource, which causes the first “Resource destroyed”.
- The temporary object is assigned to mainres by copy assignment. Since our copy assignment also does a deep copy, a new Resource is allocated, causing yet another “Resource acquired”.
- The assignment expression ends, and the temporary object goes out of expression scope and is destroyed, causing a “Resource destroyed”.
- At the end of main(), mainres goes out of scope, and our final “Resource destroyed” is displayed.
So, in short, because we call the copy constructor once to copy construct res to a temporary, and copy assignment once to copy the temporary into mainres, we end up allocating and destroying 3 separate objects in total.
Inefficient, but at least it doesn’t crash!
However, with move semantics, we can do better.
Move constructors and move assignment
C++11 defines two new functions in service of move semantics: a move constructor, and a move assignment operator. Whereas the goal of the copy constructor and copy assignment is to make a copy of one object to another, the goal of the move constructor and move assignment is to move ownership of the resources from one object to another (which is typically much less expensive than making a copy).
Defining a move constructor and move assignment work analogously to their copy counterparts. However, whereas the copy flavors of these functions take a const l-value reference parameter (which will bind to just about anything), the move flavors of these functions use non-const rvalue reference parameters (which only bind to rvalues).
Here’s the same Auto_ptr3 class as above, with a move constructor and move assignment operator added. We’ve left in the deep-copying copy constructor and copy assignment operator for comparison purposes.
The move constructor and move assignment operator are simple. Instead of deep copying the source object ( a ) into the destination object (the implicit object), we simply move (steal) the source object’s resources. This involves shallow copying the source pointer into the implicit object, then setting the source pointer to null.
When run, this program prints:
That’s much better!
The flow of the program is exactly the same as before. However, instead of calling the copy constructor and copy assignment operators, this program calls the move constructor and move assignment operators. Looking a little more deeply:
- Res is returned back to main() by value. Res is move constructed into a temporary object, transferring the dynamically created object stored in res to the temporary object. We’ll talk about why this happens below.
- Res goes out of scope. Because res no longer manages a pointer (it was moved to the temporary), nothing interesting happens here.
- The temporary object is move assigned to mainres. This transfers the dynamically created object stored in the temporary to mainres.
- The assignment expression ends, and the temporary object goes out of expression scope and is destroyed. However, because the temporary no longer manages a pointer (it was moved to mainres), nothing interesting happens here either.
So instead of copying our Resource twice (once for the copy constructor and once for the copy assignment), we transfer it twice. This is more efficient, as Resource is only constructed and destroyed once instead of three times.
Related content
Move constructors and move assignment should be marked as noexcept . This tells the compiler that these functions will not throw exceptions.
We introduce noexcept in lesson 27.9 -- Exception specifications and noexcept and discuss why move constructors and move assignment are marked as noexcept in lesson 27.10 -- std::move_if_noexcept .
When are the move constructor and move assignment called?
The move constructor and move assignment are called when those functions have been defined, and the argument for construction or assignment is an rvalue. Most typically, this rvalue will be a literal or temporary value.
The copy constructor and copy assignment are used otherwise (when the argument is an lvalue, or when the argument is an rvalue and the move constructor or move assignment functions aren’t defined).
Implicit move constructor and move assignment operator
The compiler will create an implicit move constructor and move assignment operator if all of the following are true:
- There are no user-declared copy constructors or copy assignment operators.
- There are no user-declared move constructors or move assignment operators.
- There is no user-declared destructor.
These functions do a memberwise move, which behaves as follows:
- If member has a move constructor or move assignment (as appropriate), it will be invoked.
- Otherwise, the member will be copied.
Notably, this means that pointers will be copied, not moved!
The implicit move constructor and move assignment will copy pointers, not move them. If you want to move a pointer member, you will need to define the move constructor and move assignment yourself.
The key insight behind move semantics
You now have enough context to understand the key insight behind move semantics.
If we construct an object or do an assignment where the argument is an l-value, the only thing we can reasonably do is copy the l-value. We can’t assume it’s safe to alter the l-value, because it may be used again later in the program. If we have an expression “a = b” (where b is an lvalue), we wouldn’t reasonably expect b to be changed in any way.
However, if we construct an object or do an assignment where the argument is an r-value, then we know that r-value is just a temporary object of some kind. Instead of copying it (which can be expensive), we can simply transfer its resources (which is cheap) to the object we’re constructing or assigning. This is safe to do because the temporary will be destroyed at the end of the expression anyway, so we know it will never be used again!
C++11, through r-value references, gives us the ability to provide different behaviors when the argument is an r-value vs an l-value, enabling us to make smarter and more efficient decisions about how our objects should behave.
Key insight
Move semantics is an optimization opportunity.
Move functions should always leave both objects in a valid state
In the above examples, both the move constructor and move assignment functions set a.m_ptr to nullptr. This may seem extraneous -- after all, if a is a temporary r-value, why bother doing “cleanup” if parameter a is going to be destroyed anyway?
The answer is simple: When a goes out of scope, the destructor for a will be called, and a.m_ptr will be deleted. If at that point, a.m_ptr is still pointing to the same object as m_ptr , then m_ptr will be left as a dangling pointer. When the object containing m_ptr eventually gets used (or destroyed), we’ll get undefined behavior.
When implementing move semantics, it is important to ensure the moved-from object is left in a valid state, so that it will destruct properly (without creating undefined behavior).
Automatic l-values returned by value may be moved instead of copied
In the generateResource() function of the Auto_ptr4 example above, when variable res is returned by value, it is moved instead of copied, even though res is an l-value. The C++ specification has a special rule that says automatic objects returned from a function by value can be moved even if they are l-values. This makes sense, since res was going to be destroyed at the end of the function anyway! We might as well steal its resources instead of making an expensive and unnecessary copy.
Although the compiler can move l-value return values, in some cases it may be able to do even better by simply eliding the copy altogether (which avoids the need to make a copy or do a move at all). In such a case, neither the copy constructor nor move constructor would be called.
Disabling copying
In the Auto_ptr4 class above, we left in the copy constructor and assignment operator for comparison purposes. But in move-enabled classes, it is sometimes desirable to delete the copy constructor and copy assignment functions to ensure copies aren’t made. In the case of our Auto_ptr class, we don’t want to copy our templated object T -- both because it’s expensive, and whatever class T is may not even support copying!
Here’s a version of Auto_ptr that supports move semantics but not copy semantics:
If you were to try to pass an Auto_ptr5 l-value to a function by value, the compiler would complain that the copy constructor required to initialize the function parameter has been deleted. This is good, because we should probably be passing Auto_ptr5 by const l-value reference anyway!
Auto_ptr5 is (finally) a good smart pointer class. And, in fact the standard library contains a class very much like this one (that you should use instead), named std::unique_ptr. We’ll talk more about std::unique_ptr later in this chapter.
Another example
Let’s take a look at another class that uses dynamic memory: a simple dynamic templated array. This class contains a deep-copying copy constructor and copy assignment operator.
Now let’s use this class in a program. To show you how this class performs when we allocate a million integers on the heap, we’re going to leverage the Timer class we developed in lesson 18.4 -- Timing your code . We’ll use the Timer class to time how fast our code runs, and show you the performance difference between copying and moving.
On one of the author’s machines, in release mode, this program executed in 0.00825559 seconds.
Now let’s run the same program again, replacing the copy constructor and copy assignment with a move constructor and move assignment.
On the same machine, this program executed in 0.0056 seconds.
Comparing the runtime of the two programs, (0.00825559 - 0.0056) / 0.00825559 * 100 = 32.1% faster!
Deleting the move constructor and move assignment
You can delete the move constructor and move assignment using the = delete syntax in the exact same way you can delete the copy constructor and copy assignment.
If you delete the copy constructor, the compiler will not generate an implicit move constructor (making your objects neither copyable nor movable). Therefore, when deleting the copy constructor, it is useful to be explicit about what behavior you want from your move constructors. Either explicitly delete them (making it clear this is the desired behavior), or default them (making the class move-only).
The rule of five says that if the copy constructor, copy assignment, move constructor, move assignment, or destructor are defined or deleted, then each of those functions should be defined or deleted.
While deleting only the move constructor and move assignment may seem like a good idea if you want a copyable but not movable object, this has the unfortunate consequence of making the class not returnable by value in cases where mandatory copy elision does not apply. This happens because a deleted move constructor is still a declared function, and thus is eligible for overload resolution. And return by value will favor a deleted move constructor over a non-deleted copy constructor. This is illustrated by the following program:
Issues with move semantics and std::swap Advanced
In lesson 21.12 -- Overloading the assignment operator , we mentioned the copy and swap idiom. Copy and swap also works for move semantics, meaning we can implement our move constructor and move assignment by swapping resources with the object that will be destroyed.
This has two benefits:
- The persistent object now controls the resources that were previously under ownership of the dying object (which was our primary goal).
- The dying object now controls the resources that were previously under ownership of the persistent object. When the dying object actually dies, it can do any kind of cleanup required on those resources.
When you think about swapping, the first thing that comes to mind is usually std::swap() . However, implementing the move constructor and move assignment using std::swap() is problematic, as std::swap() calls both the move constructor and move assignment on move-capable objects. This will result in an infinite recursion issue.
You can see this happen in the following example:
This prints:
And so on… until the stack overflows.
You can implement the move constructor and move assignment using your own swap function, as long as your swap member function does not call the move constructor or move assignment. Here’s an example of how that can be done:
This works as expected, and prints:
cppreference.com
std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object.
In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.
[ edit ] Parameters
[ edit ] return value.
static_cast < typename std:: remove_reference < T > :: type && > ( t )
[ edit ] Notes
The functions that accept rvalue reference parameters (including move constructors , move assignment operators , and regular member functions such as std::vector::push_back ) are selected, by overload resolution , when called with rvalue arguments (either prvalues such as a temporary object or xvalues such as the one produced by std::move ). If the argument identifies a resource-owning object, these overloads have the option, but aren't required, to move any resources held by the argument. For example, a move constructor of a linked list might copy the pointer to the head of the list and store nullptr in the argument instead of allocating and copying individual nodes.
Names of rvalue reference variables are lvalues and have to be converted to xvalues to be bound to the function overloads that accept rvalue reference parameters, which is why move constructors and move assignment operators typically use std::move :
One exception is when the type of the function parameter is a forwarding reference (which looks like an rvalue reference to type template parameter), in which case std::forward is used instead.
Unless otherwise specified, all standard library objects that have been moved from are placed in a "valid but unspecified state", meaning the object's class invariants hold (so functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from):
Also, the standard library functions called with xvalue arguments may assume the argument is the only reference to the object; if it was constructed from an lvalue with std::move , no aliasing checks are made. However, self-move-assignment of standard library types is guaranteed to place the object in a valid (but usually unspecified) state:
[ edit ] Example
Possible output:
[ edit ] See also
- 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 29 March 2024, at 05:47.
- Privacy policy
- About cppreference.com
- Disclaimers
- C++ Classes and Objects
- C++ Polymorphism
- C++ Inheritance
- C++ Abstraction
- C++ Encapsulation
- C++ OOPs Interview Questions
- C++ OOPs MCQ
- C++ Interview Questions
- C++ Function Overloading
- C++ Programs
- C++ Preprocessor
- C++ Templates
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
Please Login to comment...
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 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.
Navigation Menu
Search code, repositories, users, issues, pull requests..., provide feedback.
We read every piece of feedback, and take your input very seriously.
Saved searches
Use saved searches to filter your results more quickly.
To see all available qualifiers, see our documentation .
- Notifications You must be signed in to change notification settings
move-constructors-and-move-assignment-operators-cpp.md
Latest commit, file metadata and controls, move constructors and move assignment operators (c++).
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
IMAGES
VIDEO
COMMENTS
A move assignment operator is a non-template non-static member function with the name operator= that can be called with an argument of the same class type and copies the content of the argument, possibly mutating the argument. Syntax. For the formal move assignment operator syntax, see function declaration.
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.
We use the move assignment operator to transfer the resources from arr1 to arr2 by calling arr2 = std::move(arr1). After the move, we print the states of both arr1 and arr2. arr1 is now in a valid but unspecified state, and arr2 contains the resources of arr1.
C++11 defines two new functions in service of move semantics: a move constructor, and a move assignment operator. Whereas the goal of the copy constructor and copy assignment is to make a copy of one object to another, the goal of the move constructor and move assignment is to move ownership of the resources from one object to another (which is ...
std::move() is a cast that produces an rvalue-reference to an object, to enable moving from it. It's a new C++ way to avoid copies. For example, using a move constructor, a std::vector could just copy its internal pointer to data to the new object, leaving the moved object in an moved from state, therefore not copying all the data. This would ...
In C++, move constructors is a type of constructor that works on the r-value references and move semantics (move semantics involves pointing to the already existing object in the memory).
Unless otherwise specified, all standard library objects that have been moved from are placed in a "valid but unspecified state", meaning the object's class invariants hold (so functions without preconditions, such as the assignment operator, can be safely used on the object after it was moved from):
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. Syntax: template< class T >
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.
Preview. Code. Blame. 309 lines (245 loc) · 9.85 KB. Raw. Move Constructors and Move Assignment Operators (C++) 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.