Selected Reading

Move Semantics in C++



Move semantics are used in C++ to transfer the ownership of resources from one object to another instead of copying them. It improves the performance as it avoid unnecessary copying of objects, reducing memory usage, improves efficiency, and efficiently handles the temporary objects like rvalue.

Why Move Semantics are Needed?

Before C++11, we used to copy the resource and it was less efficient and created duplicates. In C++11, move semantics were introduced to solve this problem of memory overhead and reducing the duplicates. Here are reasons why we need move semantics −

  • Move semantics avoid copying of resources. It helps in avoiding duplicates and cause less memory overhead.
  • It handles temporary objects like rvalues.
  • It improves the performance by moving the resources instead of copying.

Expression Types in C++

An expression in C++ means any valid combination of variable, operator, constant, and function call that can give result. There are two types of expression which are as follows −

lvalue Expression

An lvalue is a type of expression in which object has a memory address and can be modified if it is not const. Example of lvalue can be a variable, array elements, and many more.

An lvalue reference is used to create a reference to an lvalue. It is denoted by (&) and is used for implementing copy semantics.

rvalue Expression

An rvalue is a type of expression that does not have a memory address and it represents a value that generally appears on the right side. It is a temporary expression that is about to get destroyed. Example of rvalue can be a constant, temporary object, and many more.

An rvalue reference is used to reference rvalues or temporary objects. It is denoted by (&&) and is used for implementing move semantics.

Here is an example of demonstrating lvalue and rvalue in C++. The x is an lvalue expression and x+5 is an rvalue expression.

#include <iostream>
using namespace std;

int main() {
    // x is an lvalue
    int x = 10;  
    // 'x + 5' is an rvalue         
    int y = x + 5;       

    cout << "Old x: " << x << endl;
    cout << "Old y: " << y << endl;

    // Demonstrating assignments
    x = 20;              // correct, as x is an lvalue
    // (x + 5) = 15;     // wrong, as x + 5 is an rvalue

    cout << "New x: " << x << endl;

    return 0;
}

The output of the above code is as follows −

Old x: 10
Old y: 15
New x: 20

The following example demonstrates lvalue reference(int &x) and rvalue reference(int &&x)

#include <iostream>
using namespace std;

void printValue(int &x){
   cout << "Calling with Lvalue reference: " << x << endl; // lvalue reference
}

void printValue(int &&x){
   cout << "Calling with Rvalue reference: " << x << endl; // rvalue reference
}

int main(){
   int a = 10;

   printValue(a);  // a is an lvalue
   printValue(20); // 20 is an rvalue

   return 0;
}