Home C++ Introduction Decisions Loops Input/Output Functions Stack and Heap References Arrays Searching and Sorting Recursion Pointers Character and Strings Structures Classes Inheritance Exceptions Templatess STL Modern C++ Misc Books ----

Move Semantics


Contents

Move Semantics lets us utilize temporary objects. We need a way of intercepting a temporary object and "steal" it's resources. In order to do that we need to distinguish between a temporary resource and a normal resource.

RValue and LValues

If we can take the address of something then it is a lvalue else it is a rvalue. If it has a name then it is a lvalue. Usually things on the left side of an assignment operator are called lvalues and the ones on the right side are called rvalues. However this is not always the case. We can also have lvalues on the right hand side of a statement. The below program shows some example of this concept.

File: values1.cpp
#include <iostream>


using namespace std ;



//Returns a rvalue
int setValue()
{
    return 6;
}

int global = 100;

int& setGlobal()
{
    return global;
}




int main()
{
    int x1 = 100 ;
    //x1 is lvalue because it has an address
    //100 is a rvalue because it is temporary and does
    //not have a permanent address in memory. It may be stored
    //in a register but after the statement,
    //it's value is lost.

    // 100 = x1 ;
    //This produces a compiler error.
    //values1.cpp: In function ‘int main()’:
    //values1.cpp:20:6: error: lvalue required as left operand of assignment
    //   20 |      100 = x1 ;
    //The "100" does not have an address and is a rvalue and we cannot
    //put it to the left as it makes no sense.
    //The left of an assignment must be a lvalue .

    //setValue() = 100 ;
    //Compiler error as the function does not return a lvalue


    setGlobal() = 100 ;
    //The above is all right because the function
    // "setGlobal" returns a lvalue .

     int x2 = x1 ;
     //Here x2 is a lvalue and x1 is also a lvalue.
     // Because x1 is a name and anything that has a name has an address.

    int& x3 = x1 ;
    //x3 is a lvalue. There is a name.
    // Right hand side x1 is also a lvale

    string str1 = "Te" ;
    string str2 = "st" ;

    //Left hand side is not a lvalue
    str1 + str2 = "Test" ;



}

RValue Reference

We are familiar with lvalue references . We also have rvalue references. A lvalue reference is initialized with a lvalue variable. However a rvalue reference must be initialized with a rvalue. Every type can have a lvalue and a rvalue. Even a rvalue referecce !

File: ref1.cpp
#include <iostream>


using namespace std ;

//This function determines if something
//is lvalue or rvalue
template <typename T>
constexpr bool is_lvalue(T&&) {
  return std::is_lvalue_reference<T>{};
}



//LVALUE REFERENCE
void function1LValueRef( int& a1 )
{
   cout << "function1:" << a1 << endl ;
}

//RVALUE REFERENCE
void function2RValueRef( int&& a1 )
{
  //Since a1 is a name it is a lvalue at this point inside the
  //function but the function can only take rvalues.
  cout << "Is a1 a lvalue: " << is_lvalue( a1 ) << endl ;
  //a1 = 25 ;
}


int main()
{
   int x1 = 10 ;
   int y1 = 30 ;


   //Need to initialize references
   int&& x2R = 20 ;
   int&& x3R = 30 ;
   int& x3L = x1  ;

   //compiler error
   //A rvalue reference must be initialized
   //int&& x7  ;
   //Can only initialize it with a temporary object
   // int&& x7 = x1  ;

   //can reassign values to r reference
   //x2R is not pointing to x3R but rather it's
   //value is being updated.
   x2R = x3R ;
   cout << "x2R:" << x2R << endl ;
   x2R = 35 ;
   cout << "x2R:" << x2R << endl ;
   //Can initialize l-value reference with r-value
   //reference. Anything that has a name is l-value.
   int& x6R = x2R ;

   //cannot initialize lvalue
   //reference with a constant/rvalue
   //At the point of definition
   //int& x8 = 25 ;
   //can do
   //const int& x1 = 20 ;

   //Can only initialize rvalue reference with
   // rvalues
   //int&& x7 = x3L ;



   function1LValueRef( x1 ) ;
   function2RValueRef(  20 ) ;


   //Allowed
   //
   x2R = x1 ;
   x2R = 40 ;   //reassignment to a r value reference

   cout << "x2R:" << x2R << endl ;
   //Not a reassignment of the lvalue reference.
   //changes the value of x1 and  x3L "points" to x1 .
   x3L = y1 ;

   //x2R's value is being set to x1
   x1 = x2R ;
   cout << "x1:" << x1 << endl ;


   //function 2 is r reference
   //Compiler error r-value reference expects a constant
   //  function2RValueRef(  x1  ) ;

    //ok move converts a l value to a r value
   function2RValueRef( move(x1)  ) ;



    //x2R is a name so it's a l value at this point
   function1LValueRef( x2R ) ;


    cout << "Is x2R a lvalue: " << is_lvalue( x2R ) << endl ;
    cout << "Is 12 a lvalue: " << is_lvalue( 12 ) << endl ;


    function2RValueRef(  move(x2R)   ) ;
    cout << "x2R value: " << x2R << endl ;
    //compiler error even though x2R is rvalue !!!
    //But it has a name so now is lvalue !!
    // function2RValueRef(  x2R   ) ;
    function2RValueRef( 21 ) ;

     int x19 = 5 ;
     cout << x19 << " " << move(x19) << endl ;

   return 0 ;
}

The key takeaway from the above code is that a rvalue reference is
declared as:

  int&& x2R = 20 ;

We can only assign a temporary value to it at this point. The
"int&&" is a type. It's lvalue is "x2R" and it's rvalue from the
above statement is "20" . Similarly in the function declaration:

//RVALUE REFERENCE
void function2RValueRef( int&& a1 )
{
  //Since a1 is a name it is a lvalue at this point inside the
  //function but the function can only take rvalues.
  cout << "Is a1 a lvalue: " << is_lvalue( a1 ) << endl ;
  //a1 = 25 ;
}

When we call this function we need to supply a rvalue. So
we can call it like this:

function2RValueRef(  20 ) ;

However we cannot do:

int&& x2R = 20 ;
function2RValueRef(  x2R   ) ;

Remember "x2R" is a name and therefore a lvalue and we
cannot initialize a rvalue reference to a lvalue. This
is the probably the most confusing part of rvalue references.

The rvalue and lvalue are sort of properties of the object and we
can change a variable from a lvalue to a rvalue with the std function
"move" and by doing this we can call our function.

function2RValueRef(  move(x2R)   ) ;

Usage

So we have the concept of rvalue references and we can assign temporary values to it but what's the advantage of this feature ? The below example shows how we can use rvalue references to take advantage of temporary objects when they are no longer needed.

File: usage1.cpp
#include <iostream>

using namespace std ;

class Holder
{
  public:

    Holder(int size)         // Constructor
    {
      cout << "Argument constructor." << size << endl ;
      printf( "%p\n" , this) ;
      m_data = new int[size];
      m_size = size;
    }

    Holder(const Holder& other)
    {
      cout << "Copy constructor." << m_size <<  endl ;
      m_data = new int[other.m_size];  // (1)
      std::copy(other.m_data, other.m_data + other.m_size, m_data);  // (2)
      m_size = other.m_size;
    }

    Holder(Holder&& other)     // <-- rvalue reference in input
    {
      cout << "Move copy constructor." << other.m_size << endl ;
      m_data = other.m_data;   // (1)
      m_size = other.m_size;
      other.m_data = nullptr;  // (2)
      other.m_size = 0;
    }

    Holder& operator=(const Holder& other)
    {
      cout << "assignment operator" << other.m_size << endl ;
      if(this == &other) return *this;  // (1)
      delete[] m_data;  // (2)
      m_data = new int[other.m_size];
      std::copy(other.m_data, other.m_data + other.m_size, m_data);
      m_size = other.m_size;
      return *this;  // (3)
    }

Holder& operator=(Holder&& other)     // <-- rvalue reference in input
{
  cout << "Move assignment operator." << other.m_size <<  endl ;

  if (this == &other)
   return *this;

  delete[] m_data;         // (1)

  m_data = other.m_data;   // (2)
  m_size = other.m_size;

  other.m_data = nullptr;  // (3)
  other.m_size = 0;

  return *this;
}


    ~Holder()                // Destructor
    {
      cout << "Destructor." << m_size << endl ;
      if ( m_data != NULL )
        delete[] m_data;
    }

  private:
    int*   m_data;
    size_t m_size;
};

Holder createHolder(int size)
{
  return Holder(size);
}


int main()
{
    //Copy constructor
    Holder h1 = createHolder(1000)  ;
    printf( "main %p\n" , &h1 ) ;
    cout << "Before Assignment.\n" << endl ;
    //Move Assignment operator
    h1 = createHolder(500);
    printf( "main %p\n" , &h1 ) ;
    cout << "End of main." << endl ;
    return 0 ;
}
$ rm a.exe ; g++ -fno-elide-constructors usage1.cpp ; ./a.exe
Argument constructor.
0x7ffffcc00
main 0x7ffffcc00
Before Assignment.

Argument constructor.
0x7ffffcc10
Move assignment operator.
Destructor.0
main 0x7ffffcc00
End of main.
Destructor.500

We have a holder class with some additonal methods that take a rvalue
reference as a parameter. One is a constructor and the other is the
assignment operator.

	Holder(const Holder& other)
	{
      cout << "Copy constructor." << endl ;
	  m_data = new int[other.m_size];  // (1)
	  std::copy(other.m_data, other.m_data + other.m_size, m_data);  // (2)
	  m_size = other.m_size;
	}

	Holder(Holder&& other)     // <-- rvalue reference in input
	{
	  cout << "Move copy constructor." << endl ;
	  m_data = other.m_data;   // (1)
	  m_size = other.m_size;
	  other.m_data = nullptr;  // (2)
	  other.m_size = 0;
	}

In the above snippet we see that with a regular copy constructor
we allocate new memory and copy the values from the argument object.
In the rvalue reference constructor we just use the argument's object pointer to
memory and set the argument's object variables to null. The reason is
so that the destructor does not destroy the "other" variables. We have
"stolen" the resources of the temporary object to make our code
more efficient.

Holder createHolder(int size)
{
  return Holder(size);
}


int main()
{
	//Copy constructor
    Holder h1 = createHolder(1000)  ;

Output
Argument constructor.
0x7ffffcc00
main 0x7ffffcc00
Before Assignment.


What should happen in the above snippet, is that the
"createHolder" returns a temporary object that gets assigned
to "h1" forcing our rvalue reference constructor to be called.
We see that the address of the object in

Holder createHolder(int size)
{
  return Holder(size);
}

is:
0x7ffffcc00

However after the "copy constructor" the address is the same:

main 0x7ffffcc00

This is because of compiler optimization. The compiler does not
destroy the initial created object and reuses it for "h1" so
no "copy constructor" gets called. We can prevent optimization
with the "-fno-elide-constructors" argument.

$ rm a.exe ; g++ -fno-elide-constructors usage1.cpp ; ./a.exe
Argument constructor.1000
0x7ffffcc00
main 0x7ffffcc00
Before Assignment.

Argument constructor.500
0x7ffffcc10
Move assignment operator.500
Destructor.0
main 0x7ffffcc00
End of main.
Destructor.500

That did not help as the compiler still did the optimization.
However we notice that:

    h1 = createHolder(500);

did cause our move assignment operator to get called.

Move assignment operator.500
Destructor.0

Once it was done with the assignment, the compiler decided
to destroy the object returned by:

createHolder(500)

Whose "m_size" is now zero as it was reset by the rvalue reference
assignment operator.



File: usage2.cpp
#include <iostream>

using namespace std ;

class Holder
{
  public:

    Holder(int size)         // Constructor
    {
      cout << "Argument constructor." << endl ;
      m_data = new int[size];
      m_size = size;
    }

    Holder(const Holder& other)
    {
      cout << "Copy constructor." << endl ;
      m_data = new int[other.m_size];  // (1)
      std::copy(other.m_data, other.m_data + other.m_size, m_data);  // (2)
      m_size = other.m_size;
    }

    Holder(Holder&& other)     // <-- rvalue reference in input
    {
      cout << "Move copy constructor." << endl ;
      m_data = other.m_data;   // (1)
      m_size = other.m_size;
      other.m_data = nullptr;  // (2)
      other.m_size = 0;
    }

    Holder& operator=(const Holder& other)
    {
      cout << "assignment operator" << endl ;
      if(this == &other) return *this;  // (1)
      delete[] m_data;  // (2)
      m_data = new int[other.m_size];
      std::copy(other.m_data, other.m_data + other.m_size, m_data);
      m_size = other.m_size;
      return *this;  // (3)
    }

Holder& operator=(Holder&& other)     // <-- rvalue reference in input
{
  cout << "Move assignment operator." << endl ;

  if (this == &other)
   return *this;

  delete[] m_data;         // (1)

  m_data = other.m_data;   // (2)
  m_size = other.m_size;

  other.m_data = nullptr;  // (3)
  other.m_size = 0;

  return *this;
}


    ~Holder()                // Destructor
    {
      cout << "Destructor." << endl ;
      if ( m_data != NULL )
        delete[] m_data;
    }

  private:
    int*   m_data;
    size_t m_size;
};

Holder createHolder(int size)
{
  return Holder(size);
}


int main()
{
    //
    Holder h1(1000)  ;
    {
        Holder h2(1000)  ;
        cout << "Before Assignment.\n" << endl ;
        //Assignment operator
        h1 = move( h2 )  ;
    }
    return 0 ;
}

$ g++ -fno-elide-constructors usage2.cpp ; ./a.exe
Argument constructor.
Argument constructor.
Before Assignment.

Move assignment operator.
Destructor.
Destructor.
The above file shows another way we can use rvalue references.

    Holder h1(1000)  ;
    {
		Holder h2(1000)  ;
		cout << "Before Assignment.\n" << endl ;
		//Assignment operator
		h1 = move( h2 )  ;
    }

We know that "h2" is going out of scope and we want to use
it's resources but it is not a rvalue. However with "move"
we change the property to rvalue and "steal" it's
resources.

Default Functions

If we don't define member functions such as constructor or the assignment operator in a class then the system defines the functions for us. The functions have "default" behavior and are called default functions. The "default" keyword introduced in C++ 11 states explicitly that the system provide the default implementation for the member function. We are talking about functions such as copy, move constructors, assignment operators. Usually the system will create the default implementation even if we don't say so but in certain cases it won't and we need to explicitly use the "default" keyword . For normal functions there is a bitwise copy of the original object. For the move member functions the system calls the move function on the data member variables and then copies them using the move operators if there are any.

File: default1.cpp
#include <iostream>


using namespace std ;

class A
{
    public:
    int x1 ;
    int x2 ;
       A(  )
        {
          cout << "A Empty constructor." << endl ;
        }

};

class B
{
    public:
       B(  )
        {
          cout << "B Empty constructor." << endl ;
        }


       B& operator=(B&& other) noexcept
       {
           cout << "B Move assignment operator for class B." << endl ;
           return *this ;
       }
};



class C
{
    public:
    B BObject1 ;

       C(  )
        {
          cout << "C Empty constructor." << endl ;
        }

      C&  operator=(C&& obj1) = default ;
};




int main()
{
   A  AObject1 ;
   AObject1.x1 = 10 ;
   AObject1.x2 = 20 ;
   A  AObject2 ;
   AObject2  = AObject1 ;
   cout <<  AObject2.x1 << " " << AObject2.x2 << endl ;

   C CObject1 ;
   C CObject2 ;
   CObject2 =  move(CObject1) ;
   return 0 ;
}



$ g++ default1.cpp ; ./a.exe
A Empty constructor.
A Empty constructor.
10 20
B Empty constructor.
C Empty constructor.
B Empty constructor.
C Empty constructor.
B Move assignment operator for class B.


The statement
AObject2  = AObject1 ;
uses the default assignment operator which is a bitwise copy and if we print the
contents of AObject2 we can see the values "10 20" that were in "AObject1" got
copied over to "AObject2" :

We then execute the statement:
CObject2 =  move(CObject1) ;

The "move" changes the "CObject1" to a RValue. And in the class we
are using the default function that the system generates for a
move assignment operator.

C&  operator=(C&& obj1) = default ;

Now the system will take "CObject1" and convert the data
members to rvalues and then copy them over to "CObject2" .
The class "C" has 1 data member which is "B BObject1 ;" .
This is converted to a rvalue and then the class B's mmove
assignment gets called.

Note that the default move methods may not be created all the time. As an example if a move constructor is already defined for a class then the system expects the move assignment operator to be defined also and will not create it for us by default.

File: default2.cpp
#include <iostream>


using namespace std ;

class A
{
    public:
    int x1 ;
    int x2 ;
       A(  )
        {
          cout << "A Empty constructor." << endl ;
        }
       //Move constructor
       A( A&& obj1  )
        {
          cout << "A Empty constructor." << endl ;
        }

};


int main()
{
   A  AObject1 ;
   AObject1.x1 = 10 ;
   AObject1.x2 = 20 ;
   A  AObject2 ;
   AObject2  = move(AObject1) ;
   cout <<  AObject2.x1 << " " << AObject2.x2 << endl ;



   return 0 ;
}


$ g++ default2.cpp
default2.cpp: In function ‘int main()’:
default2.cpp:30:29: error: use of deleted function ‘constexpr A& A::operator=(const A&)’
   30 |    AObject2  = move(AObject1) ;
      |                             ^
default2.cpp:6:7: note: ‘constexpr A& A::operator=(const A&)’ is implicitly declared as deleted because ‘A’ declares a move constructor or move assignment operator
    6 | class A
      |       ^
The above code shows that the system does not create a
default move assignment operator implementation.
If we don't need to use the move assignment operator then
the code compiles fine.
This can be illustrated by commenting out the code:
AObject2  = move(AObject1) ;

We can also tell the system to create the method explicitly
using the default keyword.



File: default3.cpp
#include <iostream>


using namespace std ;

class A
{
    public:
    int x1 ;
    int x2 ;
       A(  )
        {
          cout << "A Empty constructor." << endl ;
        }
       //Move constructor
       A( A&& obj1  )
        {
          cout << "A Empty constructor." << endl ;
        }
      A& operator=(A&& other) = default ;
};


int main()
{
   A  AObject1 ;
   AObject1.x1 = 10 ;
   AObject1.x2 = 20 ;
   A  AObject2 ;
   AObject2  = move(AObject1) ;
   cout <<  AObject2.x1 << " " << AObject2.x2 << endl ;



   return 0 ;
}




Perfect Forwarding

Let's say we have a scenario where we have a function that can take different arguments such as a reference, constant reference and rvalue reference. We want to call this function from another function that is more general and takes a template parameter. Our first attempt looks something like below.

File: notfoward1.cpp
#include <iostream>

using namespace std ;

class Object
{
 public:
  Object() = default;

  void SetName(const string &name) { name_ = move(name); }
  string GetName() const { return name_; }

 private:
  string name_;
};

void UseObject(Object& x1)
{
  cout << "calling UseObject(Object &)" << endl;
}

void UseObject(const Object& x1)
{
  cout << "calling UseObject(const Object &)" << endl;
}

void UseObject(Object&& x1)
{
  cout << "calling UseObject(Object &&)" << endl;
}

template <typename T>
void NotForwardToUseObject(T& x)
{
  UseObject(x);
}

template <typename T>
void NotForwardToUseObject(const T& x)
{
  UseObject(x);
}


template <typename T>
void NotForwardToUseObject(T&& x)
{
  cout <<  "NotForwardToUseObject:" << "Move reference." << endl ;
  UseObject(x);
}


int main()
{
  Object object;
  const Object const_object;
  UseObject(object);
  UseObject(const_object);
  UseObject(move(object));
  cout << "----" << endl;

   NotForwardToUseObject(object);
   NotForwardToUseObject(const_object);
   NotForwardToUseObject(move(object));

  cout << "----" << endl;


}


$ g++ notforward1.cpp ; ./a.exe
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &&)
----
calling UseObject(Object &)
calling UseObject(const Object &)
NotForwardToUseObject:Move reference.
calling UseObject(Object &)
----

We start by defining 3 versions of "NotForwardToUseObject" to take the
3 different parameters.

template 
void NotForwardToUseObject(T& x)

template 
void NotForwardToUseObject(const T& x)

template 
void NotForwardToUseObject(T&& x)

The debug statement inside "void NotForwardToUseObject(T&& x)" shows that
it is being called when we call "NotForwardToUseObject(move(object))" .
However when we are inside "NotForwardToUseObject" the parameter has a name
and when we call "UseObject" .

  cout <<  "NotForwardToUseObject:" << "Move reference." << endl ;
  UseObject(x);

It becomes a lvalue and we end up calling the
  UseObject(Object &)
instead of
  UseObject(Object&& x1)

We could correct the issue by having another version of "UseObject"
as shown in the next program.



File: notfoward2.cpp
#include <iostream>

using namespace std ;

class Object
{
 public:
  Object() = default;

  void SetName(const string &name) { name_ = move(name); }
  string GetName() const { return name_; }

 private:
  string name_;
};

void UseObject( Object& x1 )
{
  cout << "calling UseObject(Object &)" << endl;
}

void UseObject( const Object& x1 )
{
  cout << "calling UseObject(const Object &)" << endl;
}

void UseObject( Object&& x1 )
{
  cout << "calling UseObject(Object &&)" << endl;
}

void UseObject1( Object&& x1 )
{
  cout << "calling UseObject1(Object &&)" << endl;
}


template <typename T>
void NotForwardToUseObject( T& x1 )
{
  UseObject(x1);
}

template <typename T>
void NotForwardToUseObject( const T& x1 )
{
  UseObject(x1);
}


template <typename T>
void NotForwardToUseObject( T&& x1 )
{
  cout <<  "NotForwardToUseObject:" << "Move reference." << endl ;
  UseObject1( move(x1) );
}


int main()
{
  Object object;
  const Object const_object;
  UseObject(object);
  UseObject(const_object);
  UseObject(move(object));
  cout << "----" << endl;

   NotForwardToUseObject(object);
   NotForwardToUseObject(const_object);
   NotForwardToUseObject(move(object));

  cout << "----" << endl;


}
$ g++ notforward2.cpp ; ./a.exe calling UseObject(Object &) calling UseObject(const Object &) calling UseObject(Object &&) ---- calling UseObject(Object &) calling UseObject(const Object &) NotForwardToUseObject:Move reference. calling UseObject1(Object &&) ---- We created 1 more version "UseObject1" and are calling it from "NotForwardToUseObject" as: template void NotForwardToUseObject( T&& x1 ) { cout << "NotForwardToUseObject:" << "Move reference." << endl ; UseObject1( move(x1) ); }
Perfect forwarding allows us to write a cleaner version with fewer function calls as shown in the below program.
File: foward1.cpp
#include <iostream>

using namespace std ;

class Object
{
 public:
  Object() = default;

  void SetName(const string &name) { name_ = move(name); }
  string GetName() const { return name_; }

 private:
  string name_;
};

void UseObject(Object& x1)
{
  cout << "calling UseObject(Object &)" << endl;
}

void UseObject(const Object& x1)
{
  cout << "calling UseObject(const Object &)" << endl;
}

void UseObject(Object&& x1)
{
  cout << "calling UseObject(Object &&)" << endl;
}

template <typename T>
void NotForwardToUseObject(T x)
{
  UseObject(x);
}

template <typename T>
void ForwardToUseObject(T &&x) {
  UseObject(static_cast<T &&>(x));
}

template <typename T>
void PerfectForwardToUseObject(T &&x) {
  UseObject(forward<T>(x));
}


int main()
{
  Object object;
  const Object const_object;
  UseObject(object);
  UseObject(const_object);
  UseObject(move(object));
  cout << "----" << endl;

   NotForwardToUseObject(object);
   NotForwardToUseObject(const_object);
   NotForwardToUseObject(move(object));

  cout << "----" << endl;
  ForwardToUseObject(object);
  ForwardToUseObject(const_object);
  ForwardToUseObject(move(object));
  cout << "----" << endl;

  PerfectForwardToUseObject(object);
  PerfectForwardToUseObject(const_object);
  PerfectForwardToUseObject(move(object));

}

$ rm a.exe ; g++ forward1.cpp ; ./a.exe
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &&)
----
calling UseObject(Object &)
calling UseObject(Object &)
calling UseObject(Object &)
----
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &&)
----
calling UseObject(Object &)
calling UseObject(const Object &)
calling UseObject(Object &&)

There are certain cases where we call a function that
can take a lvalue or rvalue reference.In the above file
we can see such a function:

void UseObject(Object& x1)
{
  cout << "calling UseObject(Object &)" << endl;
}

void UseObject(const Object& x1)
{
  cout << "calling UseObject(const Object &)" << endl;
}

void UseObject(Object&& x1)
{
  cout << "calling UseObject(Object &&)" << endl;
}

template 
void NotForwardToUseObject(T x)
{
  UseObject(x);
}

We want that the right "UseObject" should be called
when we call a common function such as "NotForwardToUseObject" .
We want the "UseObject" to be called for lvalue or rvalue references.
However we know that as long as we have a name it is a lvalue. To
preserve the concept of lvalue and rvalue we have the concept of
perfect forwarding.

template 
void PerfectForwardToUseObject(T&& x) {
  UseObject(forward(x));
}

The syntax is not very intuitive or logical but we define a
template function and the argument as "T&& x".
Now with the "forward" function we can preserve the lvalue or
rvalue of the argument.