std::move in Utility in C++ | Move Semantics, Move Constructors and Move Assignment Operators - GeeksforGeeks

11 Feb, 2022
Prerequisites:
lvalue referencervalue referenceCopy Semantics (Copy Constructor)
lvalue reference
rvalue reference
Copy Semantics (Copy Constructor)
References:
In C++ there are two types of references-
lvalue reference: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 (&).rvalue reference: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 (&&).
lvalue reference: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 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 (&).
rvalue reference: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 (&&).
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.
Syntax:
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.
C++14
// C++ program to implement// the above approach // for std::string#include <string> // for std::cout#include <iostream> // for EXIT_SUCCESS macro#include <cstdlib> // for std::vector#include <vector> // for std::move()#include <utility> // Declarationstd::vector<std::string> createAndInsert(); // Driver codeint main(){    // Constructing an empty vector    // of strings    std::vector<std::string> vecString;     // calling createAndInsert() and    // initializing the local vecString    // object    vecString = createAndInsert();     // Printing content of the vector    for (const auto& s : vecString) {        std::cout << s << '\n';    }     return EXIT_SUCCESS;} // Definitionstd::vector<std::string> createAndInsert(){    // constructing a vector of    // strings with an size of    // 3 elements    std::vector<std::string> vec;    vec.reserve(3);     // constructing & initializing    // a string with "Hello"    std::string str("Hello");     // Inserting a copy of string    // object    vec.push_back(str);     // Inserting a copy of an    // temporary string object    vec.push_back(str + str);     // Again inserting a copy of    // string object    vec.push_back(std::move(str));     // Finally, returning the local    // vector    return vec;}
Hello
HelloHello
Hello
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.
vec.push_back( str + str );- This is a three-stage process-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.
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.
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.
return vec;- This is at the end of the createAndInsert() function-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.
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. 
C++14
// C++ program to implement// the above approach // for std::string#include <string> // for std::cout#include <iostream> // for EXIT_SUCCESS macro#include <cstdlib> // for std::vector#include <vector> // for std::move()#include <utility> // Declarationstd::vector<std::string> createAndInsert(); // Driver codeint main(){    // Constructing an empty vector    // of strings    std::vector<std::string> vecString;     // calling createAndInsert() and    // initializing the local vecString    // object    vecString = createAndInsert();     // Printing content of the vector    for (const auto& s : vecString) {        std::cout << s << '\n';    }     return EXIT_SUCCESS;} // Definitionstd::vector<std::string> createAndInsert(){    // constructing a vector of    // strings with an size of    // 3 elements    std::vector<std::string> vec;    vec.reserve(3);     // constructing & initializing    // a string with "Hello"    std::string str("Hello");     // Inserting a copy of string    // object    vec.push_back(str);     // Inserting a copy of an    // temporary string object    vec.push_back(str + str);     // Again inserting a copy of    // string object    vec.push_back(std::move(str));     // Finally, returning the local    // vector    return vec;}
Hello
HelloHello
Hello
Explanation:
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.
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)
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)
vec.push_back(str + str);-A temporary object will be created (str + str) with its own separate memory and will make a call to overloaded push_back() method (version 2nd  or 4th depends on the version of C++) which will steal (or moved) the data from the temporary source object (str + str) to the vector vec as it is no longer required.After performing the move the temporary object gets destroyed. Thus rather than calling the copy constructor (copy semantics), it is optimized just by copying the size of the string and manipulating pointers to the memory of the data.Here, the important point to note is that we make use of the memory which will soon no longer owns its memory. In another word, we somehow optimized it. That’s all because of the rvalue reference and move semantics.
A temporary object will be created (str + str) with its own separate memory and will make a call to overloaded push_back() method (version 2nd  or 4th depends on the version of C++) which will steal (or moved) the data from the temporary source object (str + str) to the vector vec as it is no longer required.After performing the move the temporary object gets destroyed. Thus rather than calling the copy constructor (copy semantics), it is optimized just by copying the size of the string and manipulating pointers to the memory of the data.Here, the important point to note is that we make use of the memory which will soon no longer owns its memory. In another word, we somehow optimized it. That’s all because of the rvalue reference and move semantics.
A temporary object will be created (str + str) with its own separate memory and will make a call to overloaded push_back() method (version 2nd  or 4th depends on the version of C++) which will steal (or moved) the data from the temporary source object (str + str) to the vector vec as it is no longer required.
After performing the move the temporary object gets destroyed. Thus rather than calling the copy constructor (copy semantics), it is optimized just by copying the size of the string and manipulating pointers to the memory of the data.
Here, the important point to note is that we make use of the memory which will soon no longer owns its memory. In another word, we somehow optimized it. That’s all because of the rvalue reference and move semantics.
vec.push_back(std::move(str));- Here the compiler is explicitly hinted that “object is no longer needed” named as str (lvalue reference) with the help of std::move() function by converting the lvalue reference into rvalue reference and the resource of the str will be moved to the vector. Then the state of str becomes a “valid but unspecified state”. This doesn’t matter to us because for the last time we are going to use and soon be destroyed in a moment anyway.
Lastly, return the local vector of string called vec to its caller.
In the end, returned to the caller main() function, and simply printing the elements of the local vecString vector.
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: 
Calling a std::move() on a const object usually has no effect.It doesn’t make any sense to steal or move the resources of a const object.See constObjectCallFunc() function in the below programCopy semantics is used as a fallback for move semantics if and only if copy semantics is supported.See baz() function in the below programIf there is no implementation taking the rvalue reference as an argument the ordinary const lvalue reference will be used.See baz() function in the below programIf a function or method is missing with rvalue reference as argument & const lvalue reference as an argument. Then the compile-time error will be generated.See bar() function in the below program
Calling a std::move() on a const object usually has no effect.It doesn’t make any sense to steal or move the resources of a const object.See constObjectCallFunc() function in the below program
It doesn’t make any sense to steal or move the resources of a const object.
See constObjectCallFunc() function in the below program
Copy semantics is used as a fallback for move semantics if and only if copy semantics is supported.See baz() function in the below program
See baz() function in the below program
If there is no implementation taking the rvalue reference as an argument the ordinary const lvalue reference will be used.See baz() function in the below program
See baz() function in the below program
If a function or method is missing with rvalue reference as argument & const lvalue reference as an argument. Then the compile-time error will be generated.See bar() 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- 
C++14
// C++ program to implement// the above concept // for std::cout & std::endl#include <iostream> // for std::move()#include <utility> // for std::string#include <string> // for EXIT_SUCCESS macro#include <cstdlib> // foo() taking a non-const lvalue// reference argumentvoid foo(std::string& str); // foo() taking a const lvalue// reference argumentvoid foo(const std::string& str); // foo() taking a rvalue// reference argumentvoid foo(std::string&& str); // baz() taking a const lvalue// reference argumentvoid baz(const std::string& str); // baz() taking a non-const lvalue// reference argumentvoid baz(std::string& str); // bar() taking a non-const lvalue// reference argumentvoid bar(std::string& str); // constObjectCallFunc() taking a// rvalue reference argumentvoid constObjectCallFunc(std::string&& str); // Driver codeint main(){    // foo(std::string&& str) will    // be called    foo(std::string("Hello"));     std::string goodBye("Good Bye!");     // foo(std::string& str) will be called    foo(goodBye);     // foo(std::string&& str) will be called    foo(std::move(goodBye + " using std::move()"));     std::cout << "\n\n\n";     // move semantics fallback    // baz(const std::string& str) will be called    baz(std::string("This is temporary string object"));     // baz(const std::string& str) will be called    baz(std::move(std::string(        "This is temporary string object using std::move()")));     std::cout << "\n\n\n";     std::string failToCall("This will fail to call");     /*      Reasons to fail bar() call -          1. No rvalue reference implementation           available         // First Preference          2. No const lvalue reference implementation           available    // Second Preference          3. Finally fails to invoke bar() function      */    // bar(std::move(failToCall));    // Error : check the error message for more    // better understanding    std::cout << "\n\n\n";     const std::string constObj(        "Calling a std::move() on a const object usually has no effect.");    // constObjectCallFunc(std::move(constObj));    // Error : because of const qualifier    // It doesn't make any sense to steal or    // move the resources of a const object       return EXIT_SUCCESS;} void foo(const std::string& str){    // do something    std::cout << "foo(const std::string& str) : "              << "\n\t" << str << std::endl;} void foo(std::string& str){    // do something    std::cout << "foo(std::string& str) : "              << "\n\t" << str << std::endl;} void foo(std::string&& str){    // do something    std::cout << "foo(std::string&& str) : "              << "\n\t" << str << std::endl;} void baz(const std::string& str){    // do something    std::cout << "baz(const std::string& str) : "              << "\n\t" << str << std::endl;} void baz(std::string& str){    // do something    std::cout << "baz(std::string& str) : "              << "\n\t" << str << std::endl;} void bar(std::string& str){    // do something    std::cout << "bar(std::string&& str) : "              << "\n\t" << str << std::endl;} void constObjectCallFunc(std::string&& str){    // do something    std::cout << "constObjectCallFunc(std::string&& str) : "              << "\n\t" << str << std::endl;}
foo(std::string&& str) : 
    Hello
foo(std::string& str) : 
    Good Bye!
foo(std::string&& str) : 
    Good Bye! using std::move()



baz(const std::string& str) : 
    This is temporary string object
baz(const std::string& str) : 
    This is temporary string object using std::move()
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.
 
simmytarika5
mayurkedari16
surindertarika1234
ruhelaa48
openberry
Blogathon-2021
Constructors
References
STL
Blogathon
C++
STL
CPP
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
How to Create a Table With Multiple Foreign Keys in SQL?
How to Import JSON Data into SQL Server?
Stratified Sampling in Pandas
How to Install Tkinter in Windows?
Python program to convert XML to Dictionary
Vector in C++ STL
Arrays in C/C++
Initialize a vector in C++ (6 different ways)
Inheritance in C++
Map in C++ Standard Template Library (STL)