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++)

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

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?

Kam's user avatar

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.

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.

Chris Drew's user avatar

Clearly, the two overloads are not equivalent:

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:

Dietmar Kühl's user avatar

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 .

Hot Network Questions

c custom move assignment operator

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

[ 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:

[ edit ] Notes

[ edit ] example, [ edit ] defect reports.

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

[ edit ] See also

[ edit ] External links

Powered by MediaWiki

IMAGES

  1. Introduction to C++: Logical Operators and Conditional Operators- FlexiPrep

    c custom move assignment operator

  2. Copy Constructor Assignment Operator

    c custom move assignment operator

  3. Assignment Operators In python

    c custom move assignment operator

  4. Assignment Operator in c++ and c# 31

    c custom move assignment operator

  5. Assignment Operators in C Detailed Explanation

    c custom move assignment operator

  6. Assignment Operators in C

    c custom move assignment operator

VIDEO

  1. Assignment operator in C

  2. Assignment Operator in C Programming

  3. [ Girl Streamer ] Free Fire Max Live

  4. Report

  5. Creating Objects in C#

  6. C# Tutorials

COMMENTS

  1. Implementing Move Constructor by Calling Move Assignment Operator

    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.

  2. Move Constructors and Move Assignment Operators (C++)

    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) { }

  3. c++

    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--).

  4. operator overloading

    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: