move_semantics


Concept: Move semantics

Move semantics, introduced in C++11, are a key feature that optimizes the performance of C++ programs by allowing the resources of temporary objects to be "moved" rather than copied. This is especially useful for large objects, where copying can be expensive in terms of performance. Move semantics work with a special type of constructor and assignment operator known as the move constructor and move assignment operator.

Key Concepts of Move Semantics

Rvalue and Lvalue:

Move Constructor:

A constructor that "moves" resources from a temporary object (an rvalue) to a new object, leaving the original object in a valid but unspecified state.

Move Assignment Operator:

Similar to the move constructor, but used for assigning an rvalue to an already existing object.

Benefits of Move Semantics

Example 1: Move Constructor

Let's start with a simple example where move semantics significantly improve performance.

#include <iostream>
#include <vector>

class MyClass {
public:
    int* data;
    std::size_t size;

    // Constructor
    MyClass(std::size_t s) : size(s) {
        data = new int[s];
        std::cout << "Constructed with size: " << size << std::endl;
    }

    // Destructor
    ~MyClass() {
        delete[] data;
        std::cout << "Destroyed" << std::endl;
    }

    // Copy Constructor
    MyClass(const MyClass& other) : size(other.size) {
        data = new int[size];
        std::copy(other.data, other.data + size, data);
        std::cout << "Copy Constructed" << std::endl;
    }

    // Move Constructor
    MyClass(MyClass&& other) noexcept : data(nullptr), size(0) {
        data = other.data;
        size = other.size;
        other.data = nullptr;
        other.size = 0;
        std::cout << "Move Constructed" << std::endl;
    }

    // Copy Assignment Operator
    MyClass& operator=(const MyClass& other) {
        if (this == &other)
            return *this;

        delete[] data;
        size = other.size;
        data = new int[size];
        std::copy(other.data, other.data + size, data);
        std::cout << "Copy Assigned" << std::endl;
        return *this;
    }

    // Move Assignment Operator
    MyClass& operator=(MyClass&& other) noexcept {
        if (this == &other)
            return *this;

        delete[] data;

        data = other.data;
        size = other.size;
        other.data = nullptr;
        other.size = 0;
        std::cout << "Move Assigned" << std::endl;
        return *this;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2 = std::move(obj1);  // Move construction

    MyClass obj3(20);
    obj3 = std::move(obj2);  // Move assignment

    return 0;
}

Explanation:

When to Use Move Semantics

Example 2: Move Semantics in Standard Library Containers

Standard containers like std::vector, std::string, and others leverage move semantics to improve performance during operations like resizing or reallocation.

#include <iostream>
#include <vector>

int main() {
    std::vector<MyClass> vec;
    vec.reserve(2);

    MyClass obj1(10);
    vec.push_back(std::move(obj1));  // Uses move constructor

    MyClass obj2(20);
    vec.push_back(std::move(obj2));  // Uses move constructor

    return 0;
}

Explanation:

Common Pitfalls

Summary

Move semantics are a cornerstone of modern C++ programming, allowing for more efficient code by eliminating unnecessary copies and enabling resource ownership transfer.

Previous Page | Course Schedule | Course Content