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?

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

  • DSA Tutorial
  • Data Structures
  • Linked List
  • Dynamic Programming
  • Binary Tree
  • Binary Search Tree
  • Divide & Conquer
  • Mathematical
  • Backtracking
  • Branch and Bound
  • Pattern Searching

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.

Please Login to comment...

Similar reads.

  • C++ Programs
  • Competitive Programming
  • Blogathon-2021
  • Constructors

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

22.3 — Move constructors and move assignment

A blog about C++ programming

Move Semantics: The Basics

Move Semantics

Move semantics was a new addition to C++ that arrived with C++ 11. Newer language standards have continued to expand and improve it. The feature is quite simple, but often misunderstood. I’m often reminded of that when I’m interviewing programmers.

Who will Find this Article Useful?

In this article I will cover all the basics of move semantics. This information will be useful for people that have never used move semantics but for people that are somehow familiar with the topic and use cases but don’t necessary use move semantics very often. The article will also be useful for people that want to dig deeper into the feature. And it will be useful for people that want to refresh their memory.

To benefit from this article to the fullest, you will need a good understanding of how copy constructors and assignment operators work, and you need to have a basic understanding of types and type casting.

1 – The case for Move Semantics

Before we look at the definition of move semantics, let us look at an example that will set up the premise of why move semantics exist.

1.1 – Setting the example

Let us assume that we are going to implement a struct that represents a memory block on the heap. The only thing this struct is responsible for is allocating the memory on construction and deallocating it on destruction. We can imagine that this struct is used by a complex memory allocation system. Let’s say that system is managing many instances of our struct, in other words, it is managing many memory buffers.

Here is the declaration of our struct:

We need to keep the example simple. And variables that could be needed for a robust solution, like used or free bytes and masks of all sorts, are out of the scope of this example.

1.2 – Using the Memory Buffer

Now let us also imagine that there is a free utility function that creates an array of buffers and returns the array. We can assume that this function is used by the complex memory allocation system in order to pre-allocate memory pools of different sizes.

Before C++ 11, no one would write this function in this way. Output parameters as pointer or reference will be used instead. This will make the function more complicated to implement, maintain and use. To explain why this was the case, let us have a look of how the “CreateMemoryPool” function is used. Let us assume that a bunch of pools of various sizes are created by the memory system in an “InitializePools” member function.

We will assume that we are not using any C++ 11 or newer additions to the language. We will also assume that for whatever reason the compiler will decide not to use Copy Elision to omit the copy of the return value of the “CreateMemoryPool(…)” function.

With all of these assumptions in play, calling the “CreateMemoryPool(…)” function will create a temporary return variable that will be used to assign to the member variables via the copy assignment operator of the std::vector. In other words, we are going to do a deep copy. This is very suboptimal way to write such code.

1.3 – The problem: deep copies can be very expensive

The problem with this scenario is that the local pool variable in the “CreateMemoryPool(…)” function, that stored the result of the function, will be copied into the m_PagePool and then destroyed. We are wasting a lot of cycles that way by executing extra instructions. We are also wasting cycles by allocating and deallocating memory (which is quite slow, generally speaking).

Before C++ 11, we would often reach for one of the following to minimize the allocations/deallocations caused by local and temporary variables:

  • Pass a pointer or a reference to the m_PagePool as input to the “CreateMemoryPool(…)” and let the function directly push back into the m_PagePool. In this way “CreateMemoryPool(…)” can return void, and the function is going to work directly on the variable that will store the final result of the function. And in this way we avoid copies. The first drawback is the extra parameter that is passed to the function, adding complexity. For example, doing this creates ambiguity when it comes to responsibility for the input state of that vector. Is it the callers responsibility to ensure that the vector is empty when invoking the function or will the function itself clear the vector? The second is the fact that passing a non-constant pointer or reference of the internal variable m_PagePool makes our code less safe because anyone can write code that does something bad to m_PagePool and the caller of “CreateMemoryPool(…)” loses all guarantees.
  • We can change the result of the function to return a vector of pointers to memory buffers, like so: vector<MemoryBuffer*>. This way we only copy the pointers when the “CreateMemoryPool(…)” function returns and there is no deep copying going on and no extra allocations/deallocations. The drawback to this is now the owner of the m_PagePool needs to worry about manually deallocating the pointers held by the vector, because the vector won’t do it in it own. Of course, we can use a vector of some of smart pointers to automate that part as well, but that also adds complexity.

1.4 – Move semantics solves the possible performance issue with deep copies

What we really want to do is keep the “CreateMemoryPool(…)” function implementation as it is, simple and safe, and move the result of the function directly into the m_PagePool variable without doing a deep copy, as if we are transferring water from one glass directly into another. Furthermore, we are doing even more copying by using the “push_back” function of the vector class and we want the push_back to also behave as if we are transferring water from one glass directly into another. C++ 11 and move semantics allows us to do exactly that. In the following sections, we are going to explore what move semantics are.

2 – Definition of Move Semantics

Move semantics are typically used to “steal” the resources held by another variable of the same type (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.) and leave the source variable in some valid state, rather than making a deep copy of them.

The two most common use cases for move semantics are :

  • Performance: converting an expensive deep copy operation into a cheap move, like moving the data from a source string into a target string without having to allocate/deallocate.
  • Ownership semantics: Implementing user defined data types for which copying is not allowed but moving is, like the std::unique_ptr.

3 – Lvalues, Rvalues and Xvalues

To understand how move semantics work under the hood, we need to define a few other terms. Let’s start by looking at a pseudo-code that represents an assignment statement:

The left side of the statement is what historically is called Lvalue. And the right side of the statement is what historically is called Rvalue. Of course, because of the general nature of C++ things are often more complicated. Rvalues can appear on the left side, and Lvalues on the right side. Why that is the case is not relevant for this article.

3.1 – Easy way to differentiate between Lvalues and Rvalues

You might think that the fact that Lvalues and Rvalues can appear on either side is very confusing. Fortunately, there is a very simple rule we can use to remove all this confusion. A rule that will allow us to easily classify Lvalues and Rvalues in C++.

If a variable has an identifier that you have chosen yourself, then it is an Lvalue. And if a variable does not have a name that you have deliberately selected, then it is an Rvalue. To demonstrate this rule, let’s look at the following code snippets:

Here is another example:

3.2 – Double ampersands(&&) and the new operators

Prior to C++ 11, Rvalues and Lvalues were indistinguishable. The following example code would trigger the copy constructor and the copy assignment operator of the std::vector.

This is the Copy Constructor and the Copy Assignment Operator that would have been used in both cases:

To solve this problem, C++ 11 introduced Rvalue references, denoted by a double ampersands (&&). With this addition, we can now have two different copy constructors and assignment operators. One for Lvalues and one for Rvalues.

The following code snippet shows the declaration of the copy and the move constructors:

The following code snippet shows the declaration of the copy and the move assignment operators:

We can now revisit the example from above. And we can examine how in the cases where we have an Rvalue on the right hand side, the new move constructor and move assignment operators will be called instead of the copy constructor and copy assignment.

4 – Declaring Move Constructor and Move Assignment Operator

Now we know that C++ 11 introduced Rvalue references, denoted by a double ampersands (&&). And we know that we can declare a move constructor and a move assignment operator using the Rvalue type. Let’s declare them for our MemoryBuffer struct:

5 – Defining Move Constructor and Move Assignment Operator

We now know how to declare the move constructor and move assignment operator. It is now time to define them and actually implement the useful move semantics.

What we are doing in the move constructor and the move assignment is identical, except we also need to take care of self assignment in the move assignment operator. Let’s examine what we are doing in the move constructor:

  • In the initializer list, we are copying the source m_Buffer pointer into our own internal m_Buffer pointer. This is a simple pointer copy and not a deep copy. At this point both the source and the internal m_Buffer pointers point to the same memory address.
  • Then, also in the initializer list, we are copying the variable holding the size of the source buffer into the internal m_SizeInBytes variable.
  • Then, in the move constructor body, we set the source buffer pointer to nullptr. Effectively leaving the source pointer in a valid state, but also at this point completing the process of stealing the resource. After this the internal m_Buffer pointer points to where the source m_Buffer pointer used to point.
  • Finally, we reset the m_SizeInBytes of the source to 0, effectively leaving the source MemoryBuffer in a valid state.

For completeness, here is the the entire MemoryBuffer struct:

6 – Move Semantics in Action

With the new knowledge we acquired about Lvalues and Rvalues, as well as with the implementation of the move constructor and move assignment operator, we can now revisit the example we started with and see move semantics in action.

First, let us make a small change in the “CreateMemoryPool(…)” function.

To take advantage of the new move semantics and variadic templates, in C++ 11 a new version of the vector::push_back was added to the standard library. I recommend that you check the documentation, but in a nutshell, emplace_back will construct the new MemoryBuffer right in the memory location where it will be stored by the vector and in this way reducing the need to deep copy.

And finally, let us look at the “InitializePools” member function. Notice that the code is unchanged, but the compiler will call the move assignment operator and avoid deep copy and the extra allocations/deallocations, that are quite slow.

7 – Automatic vs. Manual Move

Looking at the “MemoryAllocationSystem::Initialize()” function, we can easily conclude that if move semantics were available to the compiler and if the types in question (std::vector and MemorBuffer in this case) supports move semantics, the compiler will detect the opportunity to move instead of copy. The reason for this is that the compiler will be able to see that the local variable created and returned by the “CreateMemoryPool(…)” is in fact an Rvalue.

The compiler is unable to detect every move opportunity. We can create a situation where we, as programmers, might have the intent to move the content of one array into another array (for whatever reasons) but the compiler will not be able to automatically detect our intent to move and will fallback to a deep copy. This of course happens when we have the intention to move an Lvalue into another Lvalue. Here is an example:

By default, the compiler will correctly assume that we ask for a deep copy. And if we really want to move, then we need to help the compiler a bit and turn the right hand Lvalues into Rvalue. To explicitly tell the compiler what our intent is, C++ 11 introduced a helper function: std::move . To utilize this new helper function, we can change our example to the following:

All std::move does is a cast. It casts the “ pool1 ” variable from an Lvalue reference (&) to an Rvalue reference (&&). Doing so tells the compiler which assignment operator it should call, because the variable type changes. And of course this is all based on standard function overloading rules. In its core, the assignment operator is a function, which is overloaded for two different input types (Lvalue reference and Rvalue reference).

8 – Xvalue

The following is a bit of an extra context and not absolutely necessary for this article, but I would rather mention it. The “ pool1 ” variable, in the example above, is technically an Xvalue after the std::move is executed. For all intent and purposes, you can treat it as an Lvalue, but the language implementers need a technical term for it. It means expiring value and it denotes an Lvalue object that can be reused after a move from it was executed. There are exactly three things that can be done to an Xvalue:

  • Copy assign to the Xvalue, turning it into an Lvalue.
  • Move assign to the Xvalue, turning it into an Lvalue.
  • Call the destructor when the Xvalue goes out of scope.

9 – Special Operators’ Rules

We all know that sometimes the compiler will generate constructors and other special operators on its own. The good news is that there are rules for when the compiler will do that. And now with the new move constructor and move assignment operator, these rules have been updated. For completeness, it is worth mentioning the most important rules here.

Rule 1 : Default move operations are generated only if no copy operations or destructor is user defined. This is because C++ assumes that if you need a destructor or you manually implemented copy operations, or both, then you are dealing with some sort of resource that needs special treatment. And because it is a resource, you need to implement the move operations yourself because you, as the expert, know best how this resources should behave.

Rule 2 : Default copy operations are generated only if there is no user defined move operations. The reasons here are are the same as in Rule 1. Note that =default and =delete count as user defined.

Rule 3 : You don’t need to implement move semantics or even copy semantics manually if all of the internal member variables are of types that are movable or copyable. For example, if we were to change the “char* m_Buffer” in our MemoryBuffer class to “unique_ptr<char> m_Buffer”, then we do not need to implement the move semantics ourselves, because the unique_ptr<T> class already supports move semantics.

10 – Parameters Convention

Move semantics is an optimization that is only applicable to some use cases. In general prefer simple and conventional ways of passing information. The following table illustrates an accepted convention for passing parameters and what types you should use. When in doubt, always check it.

Move Semantics and Parameters Convention

11 – Forwarding a Reference

For completeness, I need to cover one last topic. One more function was introduced together with std::move in C++ 11. And it was std::forward.

std::forward is pretty simple as it has only one use case. Its purpose is to preserve the value type, regardless if it is Lvalue or Rvalue, and pass it on. This is also called perfect forwarding. Typically a function accepting an Rvalue will attempt to move it and invalidate it, and when this is not the case, we can use std::forwad to pass on the Rvalue down the call-stack. The following example illustrates the use case.

For completeness, it is worth mentioning that In the code example above the input “T&& inArg” is called Forwarding reference . Forwarding references are a special kind of references that preserve the value category of a function argument. In this case calling “std::forward<T>(inArg)” will preserve the input argument and will forward it as Lvalue it if the input is an Lvalue, or it will forward it as Rvalue if the input is an Rvalue.

12 – Conclusion

In general, the concept of move semantics is quite simple and as programmers we should learn how and when to use it. The concept is built based on two fundamental C++ concepts: types and function/operator overloading. The following is a list of takeaway:

  • Pre-C++ 11, value semantics sometimes lead to unnecessary and possibly expensive deep copy operations.
  • C++ 11 introduces Rvalue references to distinguish from Lvalue references. And it also introduces std::move to cast from Lvalue to Rvalue.
  • From C++ 11 on, temporary variables are treated as Rvalues.
  • Moving POD or structs composed of PODs will not give you any benefits. To get benefits from move semantics you need some kind of resource (e.g. pointers to dynamically-allocated objects, file descriptors, TCP sockets, I/O streams, running threads, etc.).

13 – Source Code

The source code containing the MemoryBuffer example is here (under MoveSemantics ). You do not need a Github account to download it. When you open the repository, click on the Code button and choose Donwload ZIP .

14 – Credit

Special thanks to my colleagues for spending their personal time proofreading, challenge this article and helping me to make it better. It is a pleasure working with every one of you!

  • Anton Andersson : Senior Gameplay Programmer at IO Interactive.
  • Nils Iver Holtar : Lead AI Programmer at IO Interactive.

Please consider sharing this post if you find the information useful.

' src=

Post navigation

Previous post.

Move assignment operator

(C++11)
(C++11)
(C++11)
General topics
statement
loop
loop (C++11)
loop
loop
statement
statement
(C++11)
Literals
(C++11)
(C++11)
expression
pointer
(C++11)
(C++11)
(C++11)

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 .

Syntax Explanation Implicitly-declared move assignment operator Deleted implicitly-declared move assignment operator Trivial move assignment operator Implicitly-defined move assignment operator Notes Example

[ edit ] Syntax

class_name class_name ( class_name ) (1) (since C++11)
class_name class_name ( class_name ) = default; (2) (since C++11)
class_name class_name ( class_name ) = delete; (3) (since C++11)

[ 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

  • Getting started with C++
  • Awesome Book
  • Awesome Community
  • Awesome Course
  • Awesome Tutorial
  • Awesome YouTube
  • Argument Dependent Name Lookup
  • Arithmitic Metaprogramming
  • Atomic Types
  • Basic input/output in c++
  • Basic Type Keywords
  • Bit Manipulation
  • Bit Operators
  • Build Systems
  • C incompatibilities
  • C++ Containers
  • C++ Debugging and Debug-prevention Tools & Techniques
  • C++ function "call by value" vs. "call by reference"
  • C++ Streams
  • C++11 Memory Model
  • Callable Objects
  • Classes/Structures
  • Client server examples
  • Common compile/linker errors (GCC)
  • Compiling and Building
  • Concurrency With OpenMP
  • Const Correctness
  • const keyword
  • Constant class member functions
  • Copy Elision
  • Copying vs Assignment
  • Curiously Recurring Template Pattern (CRTP)
  • Data Structures in C++
  • Date and time using header
  • Design pattern implementation in C++
  • Digit separators
  • Enumeration
  • Explicit type conversions
  • Expression templates
  • Floating Point Arithmetic
  • Flow Control
  • Fold Expressions
  • Friend keyword
  • Function Overloading
  • Function Template Overloading
  • Futures and Promises
  • Header Files
  • Implementation-defined behavior
  • Inline functions
  • Inline variables
  • Internationalization in C++
  • Layout of object types
  • Linkage specifications
  • Memory management
  • Metaprogramming
  • More undefined behaviors in C++
  • Move Semantics
  • Move semantics
  • Move assignment
  • Move constructor
  • Re-use a moved object
  • Using move semantics on containers
  • Using std::move to reduce complexity from O(n²) to O(n)
  • mutable keyword
  • Non-Static Member Functions
  • One Definition Rule (ODR)
  • Operator Overloading
  • operator precedence
  • Optimization
  • Optimization in C++
  • Overload resolution
  • Parameter packs
  • Perfect Forwarding
  • Pimpl Idiom
  • Pointers to members
  • Polymorphism
  • Preprocessor
  • RAII: Resource Acquisition Is Initialization
  • Random number generation
  • Recursion in C++
  • Recursive Mutex
  • Refactoring Techniques
  • Regular expressions
  • Resource Management
  • Return Type Covariance
  • Returning several values from a function
  • RTTI: Run-Time Type Information
  • SFINAE (Substitution Failure Is Not An Error)
  • Side by Side Comparisons of classic C++ examples solved via C++ vs C++11 vs C++14 vs C++17
  • Singleton Design Pattern
  • Smart Pointers
  • Special Member Functions
  • Standard Library Algorithms
  • static_assert
  • std::atomics
  • std::forward_list
  • std::function: To wrap any element that is callable
  • std::integer_sequence
  • std::iomanip
  • std::optional
  • std::set and std::multiset
  • std::string
  • std::variant
  • std::vector
  • Storage class specifiers
  • Stream manipulators
  • The ISO C++ Standard
  • The Rule of Three, Five, And Zero
  • The This Pointer
  • Thread synchronization structures
  • Trailing return type
  • type deduction
  • Type Erasure
  • Type Inference
  • Type Keywords
  • Type Traits
  • Typedef and type aliases
  • Undefined Behavior
  • Unit Testing in C++
  • Unnamed types
  • Unspecified behavior
  • User-Defined Literals
  • Using declaration
  • Using std::unordered_map
  • Value and Reference Semantics
  • Value Categories
  • Variable Declaration Keywords
  • Virtual Member Functions

C++ Move Semantics Move assignment

Fastest entity framework extensions.

Similarly to how we can assign a value to an object with an lvalue reference, copying it, we can also move the values from an object to another without constructing a new one. We call this move assignment. We move the values from one object to another existing object.

For this, we will have to overload operator = , not so that it takes an lvalue reference, like in copy assignment, but so that it takes an rvalue reference.

This is the typical syntax to define move assignment. We overload operator = so that we can feed it an rvalue reference and it can assign it to another object.

Thus, we can move assign an object to another one.

Got any C++ Question?

pdf

  • Advertise with us
  • Cookie Policy
  • Privacy Policy

Get monthly updates about new articles, cheatsheets, and tricks.

Stack Exchange Network

Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

C++11 Vector with move semantics

I am practicing move semantics and placement new by writing a custom Vector class but I am not confident that I use them right. I would really appreciate some pieces of advice regarding my code.

Here is my Vector header

My Vector implementations are in a separate header for readability purposes.

And I will just post the code for one of the iterators type, because the rest are identical.

Sᴀᴍ Onᴇᴌᴀ's user avatar

  • \$\begingroup\$ Ooooh. This is a big NoNo. _NOEXCEPT Leading underscore followed by a capitol letter. Don't do that. In fact why have it at all. We know your code needs to be at least C++11 as it has move semantics built in and C++11 has the keyword noexcept . \$\endgroup\$ –  Loki Astari Commented Jan 14, 2019 at 17:17
  • \$\begingroup\$ Please don't edit your code to incorporate advice from answers. I rolled back your last edit. After getting an answer you are not allowed to change your code anymore. This is to ensure that answers do not get invalidated and have to hit a moving target. If you have changed your code you can either post it as an answer (if it would constitute a code review) or ask a new question with your changed code (linking back to this one as reference). Refer to this post for more information \$\endgroup\$ –  Sᴀᴍ Onᴇᴌᴀ ♦ Commented Jan 14, 2019 at 18:50
  • \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ: If you look at those changes, they were pure whitespace/formatting that looked like unintentional copy/paste problems or something. Martin York's answer addresses this mess, but I'm not sure it was even intentional in the first place. I mean it seems so obviously bad style that I hope nobody did that on purpose, but it is possible. Maybe the OP can clarify. \$\endgroup\$ –  Peter Cordes Commented Jan 14, 2019 at 18:56
  • 1 \$\begingroup\$ @peterCordes I thought that at first as well, but then on further inspection I noticed that the member variables had been split, per Martin's advice: " My gosh. private: T *m_data; size_t m_size; size_t m_capacity; One variable per line please. " \$\endgroup\$ –  Sᴀᴍ Onᴇᴌᴀ ♦ Commented Jan 14, 2019 at 18:58
  • 1 \$\begingroup\$ @SᴀᴍOnᴇᴌᴀ: They commented on Martin's answer that it was a copy/paste glitch. Still unfortunate to waste people's time reviewing an unintentionally badly formatted question, but that damage is already done and the long-term usefulness of this question is probably improved if we let the formatting accidents be fixed. \$\endgroup\$ –  Peter Cordes Commented Jan 14, 2019 at 19:08

2 Answers 2

  • We have consistently misspelt std::size_t .
  • _NOEXCEPT is a reserved identifier and may even be expanded as a macro.
  • We should have an initializer-list constructor - as a guide, construction and assignment argument lists should parallel each other.
  • inline is redundant and just adds clutter.
  • makeSpace() has no return statement.
  • Logging output should go to std::clog , not std::cout .
  • Outside of the class definition, the return type of insert() and other functions must be written as typename Vector<T>::iterator rather than Vector::iterator (or use trailing return type syntax).
  • Don't assume that an input iterator has operator-() (but do provide optimised overloads where std::distance() is usable).
  • We can't use T::operator= to populate uninitialized memory with an object - we need to construct in-place, or use one of the std::uninitialized_copy() family of functions.
  • We don't need moveFrom_() if we implement move construction and assignment using swap() .
  • We can simplify copy-assign by implementing it in terms of move-assign (see below).
  • Relational operators could be simpler, if we used std::lexicographical_compare() instead of writing those loops.
  • The contains() member function is equivalent to calling std::find() and comparing the result against an end iterator.
  • There's too much whitespace for my taste - I'd certainly remove that around the . operator, and I suggest grouping related declarations on adjacent lines. Spaces around < and > makes template arguments harder to distinguish from the < and > operators.
  • Inheriting from std::iterator is now deprecated.
  • We could use std::reverse_iterator to create a reverse iterator from a forward iterator.
  • We could use a plain pointer as forward iterator.

Regarding the iterators, I successfully replaced those four files with:

We need to also remove the -1 from the reverse begin/end (and we can further simplify):

Copy-assign implemented in terms of move-assign:

We can't implement copy-construct the same way, because passing by value depends on copy-construction, giving us a chicken-and-egg issue!

Toby Speight's user avatar

  • \$\begingroup\$ @TobySpeight This surpassed my expectations. Learnt so much! Can't say Thank you enough \$\endgroup\$ –  user188494 Commented Jan 14, 2019 at 17:53
  • 3 \$\begingroup\$ The copy-assign version is certainly neat syntax-wise... however it's not as efficient as it could be. If *this happens to have enough capacity for rhs.size() elements, then no allocation should be necessary. \$\endgroup\$ –  Matthieu M. Commented Jan 14, 2019 at 18:59
  • \$\begingroup\$ Good point @Matthieu \$\endgroup\$ –  Toby Speight Commented Jan 14, 2019 at 19:06
  • \$\begingroup\$ @MatthieuM. Well, one should then also look at whether copy-constructing an element can throw. \$\endgroup\$ –  Deduplicator Commented Jan 14, 2019 at 21:06
  • 1 \$\begingroup\$ @Michaela: Yes. So will using a naive for-loop instead of a vectorized copy when T is trivially copyable. There's always room for improvement :) Once you get the broad strokes right, though, unless you have very specific performance requirements... Don't sweat the small stuff . First make sure to get it right, then eliminate "gross" performance issues: (1) algorithmic, (2) memory, and only then start looking into micro-optimizations if it's still needed. \$\endgroup\$ –  Matthieu M. Commented Jan 15, 2019 at 9:16

You need to use namespaces in your code. Nearly everybody and their granddaughter builds a Vector class at some point. So the likelhood of a clash is very high. Build yours into your own namespace (then you get not clashes).

Code Review

This is a good start.

But does not look very unique to me (especially since everybody builds a Vector ). Add the namespace into this guard and you will have something at least reasonably unique.

Don' do this.

In addition to _NOEXCEPT being a reserved identifier; why are you trying to obfuscate your code? Just put noexcept out there. Everybody understands it nowadays.

That's a lot to put on one line!

In the rest of your code you put an empty line between every function (which I also find annoying) but here you force FOUR different things on a single line. Give the reader a break this needs to be broken up. Also group your methods into logical groups.

OK. This is a good constructor. But do you actually need to specify a default value? Can that not be inferred by the value taking on the default constructed version of the type?

I wish you would break the template stuff onto one row and the method stuff onto another row. That's a more common way of writing these declarations.

OK. I see assignment to an initializer list but given this why can't I construct the vector with an initializer list? While we are at it why do you pass initializer lists by value? See comments below.

Nice Standard set of push operations.

But why don't I see an emplace_back() in the same area? Am I going to find it below?

Including other header files inside a class (and thus probably a namespace). That's not a disaster waiting to happen (sarcasm). These header files are dependent on this header file. What happens if a user includes them directly. You should at least set up some header guards that makes it hard to do that accidentally.

Don't really think you need any special iterator classes for a vector. A pointer to the member should work just fine (assuming contiguous memory for the data).

One variable per line please. Also brave of you to use T* as the pointer type. Let's see if you get the allocation correct.

Not sure why these are standalone methods. Why are they not members of the class?

OK. Copy swap idiom usually does not check for self-assignment.

Yes. A self-assignment check will save you a lot if you actually do a self-assignment. But self-assignment is so vanishingly rare that you are actually pessimizing the normal action. Now this pessimization is a small cost but done so very frequently that the overall cost is on average higher than the cost of a self-assignment copy.

The standard way of writing this is:

Community's user avatar

  • 2 \$\begingroup\$ 1. I havent actually written my code like that with 1000 stuff on one line. It just got reformatted when I copied-pasted. I will fix it now. 2.I have heard it's a good practice to overload some operators as non-member functions. E.g [ stackoverflow.com/questions/29999932/… 3. I think emplace_back should use variadic template arguments, something I havent read anything about yet, which is why it is not there. \$\endgroup\$ –  user188494 Commented Jan 14, 2019 at 18:36
  • 1 \$\begingroup\$ Non-member comparison operators do make sense, according to the common guideline (they can be implemented using the public interface, so don't make them members). \$\endgroup\$ –  Toby Speight Commented Jan 14, 2019 at 18:44
  • 1 \$\begingroup\$ std::initializer_list is a reference type, and always passed by value, unless perfect forwarding interferes. The comparison-operators are probably not members because there is no need for them to be. Also, it allows for more flexibility when allocator-support is added later. \$\endgroup\$ –  Deduplicator Commented Jan 14, 2019 at 21:28
  • \$\begingroup\$ Copy-assignment with move-semantics: return *this = Vector(rhs); . \$\endgroup\$ –  Deduplicator Commented Jan 15, 2019 at 14:30

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 and acknowledge you have read our privacy policy .

  • The Overflow Blog
  • Navigating cities of code with Norris Numbers
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites

Hot Network Questions

  • Guitar amplifier placement for live band
  • ambobus? (a morphologically peculiar adjective with a peculiar syntax here)
  • Discrete cops and robbers
  • Dial “M” for murder
  • Why do these finite group Dedekind matrices seem to have integer spectrum when specialized to the order of group elements?
  • An interesting example of Horizontal and Vertical Lines in TIKZ?
  • Are there jurisdictions where an uninvolved party can appeal a court decision?
  • Does the Ghost achievement require no kills?
  • What is the legal status of the Avengers before Civil War and after Winter Soldier?
  • Garage door not closing when sunlight is bright
  • Name of a YA book about a girl who undergoes secret experimental surgery that makes her super smart
  • Sci-fi book about humanity warring against aliens that eliminate all species in the galaxy
  • How to cite a book if only its chapters have DOIs?
  • Why was I was allowed to bring 1.5 liters of liquid through security at Frankfurt Airport?
  • Questions about best way to raise the handlebar on my bike
  • How do you "stealth" a relativistic superweapon?
  • Has anybody replaced a LM723 for a ua723 and experienced problems with drift and oscillations
  • Enigmatic Puzzle 4: Three Leaf Clover
  • Why is たってよ used in this sentence to denote a request?
  • What is the purpose of toroidal magnetic field in tokamak fusion device?
  • How to allow just one user to use the SSH
  • Do temperature variations make trains on Mars impractical?
  • What majority age is taken into consideration when travelling from country to country?
  • What does it mean to have a truth value of a 'nothing' type instance?

move assignment vector

Move assignment operator

(C++11)
(C++11)
(C++11)
(C++17)
General
Members
pointer
(C++11)
specifier
specifier
Special member functions
(C++11)
(C++11)
Inheritance
(C++11)
(C++11)

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

class_name class_name ( class_name ) (1) (since C++11)
class_name class_name ( class_name ) = default; (2) (since C++11)
class_name class_name ( class_name ) = delete; (3) (since C++11)

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;
(until C++14)

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);
has a non-static data member or a direct or virtual base without a move assignment operator that is not trivially copyable; has a direct or indirect virtual base class. (until C++14)

A deleted implicitly-declared move assignment operator is ignored by .

(since C++14)

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;
has no non-static data members of -qualified type. (since C++14)

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

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:

V { V& operator=(V&& other) { // this may be called once or twice // if called twice, 'other' is the just-moved-from V subobject return *this; } }; struct A : virtual V { }; // operator= calls V::operator= struct B : virtual V { }; // operator= calls V::operator= struct C : B, A { }; // operator= calls B::operator=, then A::operator= // but they may only called V::operator= once   int main() { C c1, c2; c2 = std::move(c1); }
(since C++14)

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.

cppreference.com

Std::vector<t,allocator>:: vector.

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
Tables

vector::cbegin (C++11)
vector::cend (C++11)
vector::crbegin (C++11)
vector::crend (C++11)
)

operator!=operator<operator>operator<=operator>=operator<=> (until C++20)(until C++20)(until C++20)(until C++20)(until C++20)(C++20)
erase_if(std::vector) (C++20)




(1)
); (until C++17)
) noexcept(noexcept(Allocator())); (since C++17)
(constexpr since C++20)
(2)
vector( const Allocator& alloc ); (until C++17)
vector( const Allocator& alloc ) noexcept; (since C++17)
(constexpr since C++20)
(3)
vector( size_type count,

                 const T& value = T(),

                 const Allocator& alloc = Allocator() );
(until C++11)
size_type count,

        const T& value,

        const Allocator& alloc = Allocator() );
(since C++11)
(constexpr since C++20)
(4)
vector( size_type count ); (since C++11)
(until C++14)
vector( size_type count,
                 const Allocator& alloc = Allocator() );
(since C++14)
< class InputIt >

vector( InputIt first, InputIt last,

        const Allocator& alloc = Allocator() );
(5) (constexpr since C++20)
const vector& other ); (6) (constexpr since C++20)
const vector& other, const Allocator& alloc ); (7) (since C++11)
(constexpr since C++20)
vector&& other ); (8) (since C++11)
(noexcept since C++17)
(constexpr since C++20)
vector&& other, const Allocator& alloc ); (9) (since C++11)
(constexpr since C++20)
<T> init,
        const Allocator& alloc = Allocator() );
(10) (since C++11)
(constexpr since C++20)
template< <T> R >

constexpr vector( , R&& rg,

                  const Allocator& alloc = Allocator() );
(11) (since C++23)

Constructs a new container from a variety of data sources, optionally using a user supplied allocator alloc .

This constructor has the same effect as vector(static_cast<size_type>(first), static_cast<value_type>(last), a) if is an integral type.

(until C++11)

This overload participates in overload resolution only if satisfies , to avoid ambiguity with the overload (3).

(since C++11)

The allocator is obtained as if by calling <allocator_type>::select_on_container_copy_construction(
    other.get_allocator()).

(since C++11)

During , only the first argument contributes to the deduction of the container's template parameter.

(since C++23)
Parameters Complexity Exceptions Notes Example Defect reports See also

[ edit ] Parameters

alloc - allocator to use for all memory allocations of this container
count - the size of the container
value - the value to initialize elements of the container with
first, last - the range first last to copy the elements from
other - another container to be used as source to initialize the elements of the container with
init - initializer list to initialize the elements of the container with
rg - a , that is, an whose elements are convertible to

[ edit ] Complexity

  • If first and last are both forward, bidirectional or random-access iterators,
  • The copy constructor of T is only called N   times, and
  • No reallocation occurs.
  • Otherwise ( first and last are just input iterators),
  • The copy constructor of T is called O(N) times, and
  • Reallocation occurs O(log N) times.
  • If R models ranges::forward_range or ranges::sized_range ,
  • Initializes exactly N elements from the result of dereferencing successive iterators of rg , and
  • Otherwise ( R models input range),
  • The copy or move constructor of T is called O(N) times, and

[ edit ] Exceptions

Calls to Allocator :: allocate may throw.

[ edit ] Notes

After container move construction (overload (8) ), references, pointers, and iterators (other than the end iterator) to other remain valid, but refer to elements that are now in * this . The current standard makes this guarantee via the blanket statement in [container.reqmts]/67 , and a more direct guarantee is under consideration via LWG issue 2321 .

The overload (4) zeroes out elements of non-class types such as int , which is different from the behavior of new[] , which leaves them uninitialized. To match the behavior of new [ ] , a custom Allocator::construct can be provided which leaves such elements uninitialized.

Note that the presence of list-initializing constructor (10) means list initialization and direct initialization do different things:

macro Value Std Feature
202202L (C++23) construction and insertion; overload ( )

[ edit ] Example

[ edit ] defect reports.

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

DR Applied to Behavior as published Correct behavior
C++98 overload (5) allowed up to 2N  copy
constructor calls in the input iterator case
changed to O(N) calls
C++98 for overload (4), the elements in the container were default constructed they are value-initialized
C++11 the default constructor is explicit made non-explicit

[ edit ] See also

assigns values to the container
(public member function)
assigns values to the container
(public member function)
  • 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 5 November 2023, at 12:01.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

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.

Get early access and see previews of new features.

Copying std::vector: prefer assignment or std::copy?

I have two vectors:

And now I need to copy v1 to v2 . Is there any reason to prefer

std::copy (v1.begin(), v1.end(), v2.begin());

(or vice versa)?

Violet Giraffe's user avatar

  • 7 Assignment operator will do the right thing. The way you've written copy , it'll mess up if v1 is larger than v2 . –  jrok Commented Feb 20, 2013 at 10:36
  • 5 If v1 is not required after the copy you could just v2.swap(v1); . –  hmjd Commented Feb 20, 2013 at 10:38
  • 1 Write what you want to do. If you want to assign one vector to another, write that. –  Alex Chamberlain Commented Feb 20, 2013 at 10:52

6 Answers 6

Generally I would strongly prefer v2 = v1 :

  • It is shorter and makes the intent more clear
  • std::copy won't work if v2 doesn't have the same length as v1 (it won't resize it, so it will retain some of the old elements best case ( v2.size() > v1.size() and overwrite some random data used elsewhere in the program worst case
  • If v1 is about to expire (and you use C++11) you can easily modify it to move the contents
  • Performancewise assignment is unlikely to be slower then std::copy , since the implementers would probably use std::copy internally, if it gave a performance benefit.

In conclusion, std::copy is less expressive, might do the wrong thing and isn't even faster. So there isn't really any reason to use it here.

devoured elysium's user avatar

  • 19 Then, what is std::copy for? –  altroware Commented Jul 6, 2015 at 10:27
  • 46 @altroware: It's for general copying from one range to another. You can't, for example, use the assignment operator to copy from a std::list to a std::vector , or from one portion of a std::vector to another portion of the same std::vector . –  Benjamin Lindley Commented Sep 15, 2015 at 18:10
  • 4 What will happen if v1 was allocated on the stack and gets destructed? Does v2 = v1 cause elements of v1 to be copied? –  James Wierzba Commented Apr 7, 2016 at 14:57
  • Which copy mechanism of the element type is called? In this case of vector<int> , are the integers copied from one vector to the other with operator= , or with int 's copy constructor? –  Gauthier Commented Nov 9, 2016 at 8:33
  • 2 @james operator= Will do a full deep copy. Idiomatic C++ uses value semantics so copying a vector copies all its elements. The exception is if it’s elements are pointers in which case the pointers are copied. After assignment, the vectors are independent. –  Ben Commented Oct 24, 2021 at 1:26

If v2 isn't big enough you'll get a buffer overrun if you use copy as you have.

You can use a back insert iterator which will call push_back on v2 . However this could lead to multiple reallocations depending upon how big v1 is.

You're better off letting vector manage things correctly. The assignment operator does this, as does vector::assign :

I have an inkling that the assignment operator is implemented in terms of vector::assign .

Open AI - Opting Out's user avatar

  • Mr. Wood, is it possible that you meant v2.assign(v1.begin(), v1.end()) rather than v2.assign(v1.begin(), v2.end())? –  Peter Schaeffer Commented Dec 21, 2015 at 3:20

The invocation of std::copy may try to access items beyond the end of the destination vector.

Use assignment.

It's not your job to micro-optimize: that's the library writer's responsibility, and ultimately the compiler's responsibility.

You can make your code arbitrarily fast if it doesn't have to be correct.

In the case of the copy , however, it's rather doubtful whether it even is faster, and it's certainly not correct for the general case.

Cheers and hth. - Alf's user avatar

  • 3 I agree with your statements concerning optimization, but it might be worth pointing out that the more information available to the compiler or the library, the better it can do its job. Member functions of std::vector know that they're working on an std::vector , and know how it is implemented. std::copy doesn't have this information. The conclusion is that the member functions can probably do the job better (and certainly not worse). –  James Kanze Commented Feb 20, 2013 at 10:38

Assignment, by far. More generally, any time the size of the vector might change, or change the entire contents of the vector, you should prefer member functions. The only time std::copy would be appropriate is if you are only replacing a small range totally within the vector.

James Kanze's user avatar

It's shorter.

std::copy is mainly meant for copying sections of containers. If you need to copy an entire container, you might as well use the copy constructor.

Symaxion's user avatar

  • If v2 isn't big enough you'll get a buffer overrun. –  Open AI - Opting Out Commented Feb 20, 2013 at 10:36

Assignement is clearer and internally uses std::copy (or unitizalized_copy _M_allocate_and_copy depending size and capacity) or so performances are the same.

FredericS's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

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 and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ stl copy or ask your own question .

  • The Overflow Blog
  • Navigating cities of code with Norris Numbers
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • Feedback requested: How do you use tag hover descriptions for curating and do...

Hot Network Questions

  • Advice needed: Team needs developers, but company isn't posting jobs
  • Terminal autocomplete (tab) not completing when changing directory up one level (cd ../)
  • Can I cast True Strike, then cast Message to give someone else advantage?
  • Colorless Higgs
  • Can I use "Member, IEEE" as my affiliation for publishing papers?
  • Why does the definition of a braided monoidal category not mention the braid equation?
  • How do you "stealth" a relativistic superweapon?
  • Function for listing processes holding a specified file open
  • Does the expansion of space imply anything about the dimensionality of the Universe?
  • Polar coordinate plot incorrectly plotting with PGF Plots
  • What does it mean to have a truth value of a 'nothing' type instance?
  • How to read data from Philips P2000C over its serial port to a modern computer?
  • How predictable are the voting records of members of the US legislative branch?
  • Word to classify what powers a god is associated with?
  • Garage door not closing when sunlight is bright
  • How to allow just one user to use the SSH
  • Ways to paint a backbone on a tree
  • Non-linear recurrence for rational sequences with generating function with radicals?
  • Can I use the Chi-square statistic to evaluate theoretical PDFs against an empirical dataset of 60,000 values?
  • Has anybody replaced a LM723 for a ua723 and experienced problems with drift and oscillations
  • Stargate "instructional" videos
  • Why isn't openvpn picking up my new .conf file?
  • Unreachable statement wen upgrading APEX class version
  • Why is たってよ used in this sentence to denote a request?

move assignment vector

COMMENTS

  1. Move assignment operator

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

  2. STL vector: Moving all elements of a vector

    A = std::move(B); Now A contains the elements that were previously held by B, and B is now empty. This avoids copying: the internal representation is simply moved from B to A, so this is an O(1) solution. As for C++03, as Prætorian states, you could swap the vectors. There is a specialization of the std::swap function, which takes std::vector ...

  3. Move Assignment Operator in C++ 11

    The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.

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

  5. std::move in Utility in C++

    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. ... In C++ programming, we have a feature called the move assignment operator, which was introduced in C++11. It helps us handle objects more efficiently, especially when it comes to managing ...

  6. 22.3

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

  7. Move Semantics: The Basics

    3 - Lvalues, Rvalues and Xvalues. To understand how move semantics work under the hood, we need to define a few other terms. Let's start by looking at a pseudo-code that represents an assignment statement: L = R. The left side of the statement is what historically is called Lvalue.

  8. Move assignment operator

    The move assignment operator is called whenever it is selected by overload resolution, ... For example, move-assigning from a std:: string or from a std:: vector leaves the right-hand side argument empty. Implicitly-declared move assignment operator. If no user-defined move assignment operators are provided for a class type ...

  9. Move constructors

    Triviality of eligible move constructors determines whether the class is an implicit-lifetime type, and whether the class is a trivially copyable type. [] NoteTo make the strong exception guarantee possible, user-defined move constructors should not throw exceptions. For example, std::vector relies on std::move_if_noexcept to choose between move and copy when the elements need to be relocated.

  10. std::move

    Return value. static_cast < typename std:: remove_reference < T >:: type && > (t) [] NoteThe 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 ...

  11. C++ Tutorial => Move assignment

    A& operator= (A&& other) {. this->a = other.a; other.a = 0; return *this; This is the typical syntax to define move assignment. We overload operator = so that we can feed it an rvalue reference and it can assign it to another object. Thus, we can move assign an object to another one.

  12. C++ : Move Assignment Operator :: AlgoTree

    String class : Move assignment operator - Parameter: The move assignment operator for a class takes an rvalue reference ( && ) to the class type as its parameter. String& operator = (String&& obj) {. . . } - Check before assigning: To prevent an object getting assigned to itself, a conditional block is used. - Do the assignment - Release the source pointer to avoid multiple free operations by ...

  13. Vector with move constructor and move assignment operator

    3. Now you can release the old resources. This is unlikely to go wrong; But even if something goes wrong your object is in a good state. So your Copy assignment should look like this: MyVector& operator=(const MyVector& rhs) {. // Make a copy to temp. std::size_t tSize = rhs.m_Size; int* tInt = new int[tSize];

  14. Why std::move is required to invoke move assign operator of std::vector

    aaa(std::move(foo)); return 0; } The result of the is: size of a before move: 3. size of a after move: 3. It seems the move assign operator of std::vector is not invoked at line v = a in function aaa, otherwise a would have size 0 instead of 3. However if i change v = a to v = std::move(a) the output became.

  15. std::vector<T,Allocator>::operator=

    1) Copy assignment operator. Replaces the contents with a copy of the contents of other . If std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::value is true, the allocator of *this is replaced by a copy of other. If the allocator of *this after assignment would compare unequal to its old value, the old allocator is ...

  16. C++11 Vector with move semantics

    8. I am practicing move semantics and placement new by writing a custom Vector class but I am not confident that I use them right. I would really appreciate some pieces of advice regarding my code. Here is my Vector header. Vector( size_t, const T & ); template < typename InputIterator > Vector( InputIterator, InputIterator ); Vector( const ...

  17. 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--). If it is copy-constructed, we will be ...

  18. Move assignment operator

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

  19. Move assignment in overloaded vector summation

    There is a move elision takes place. According to the C++ 17 Standard (12.8 Copying and moving class objects) 31 When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source ...

  20. std::vector<T,Allocator>::vector

    constexpr vector (std::from_range_t, R && rg, const Allocator& alloc = Allocator()); (11) (since C++23) Constructs a new container from a variety of data sources, optionally using a user supplied allocator alloc . 1) Default constructor. Constructs an empty container with a default-constructed allocator. 2) Constructs an empty container with ...

  21. Copying std::vector: prefer assignment or std::copy?

    If v1 is about to expire (and you use C++11) you can easily modify it to move the contents. Performancewise assignment is unlikely to be slower then std::copy, since the implementers would probably use std::copy internally, if it gave a performance benefit. In conclusion, std::copy is less expressive, might do the wrong thing and isn't even faster.