article cpp c++
Posted in

C++ and move semantics

Move semantics makes it possible for compilers to replace expensive copying operations with less expensive moves. In the same way that copy constructors and copy assignment operators give you control over what it means to copy objects, move constructors and move assignment operators offer control over the semantics of moving. Move semantics also enables the creation of move-only types, such as std::unique_ptr, std::future, and std::thread.

At runtime, neither does anything at all. They generate no executable code. Not a single byte.

What happens during swap method

template<typename T>
void foo(T& a, T& b) {
    auto tmp = a;
    a = b;
    b = tmp;
}

What happens:

copy swap variant cpp

What we expect to happen:

move swap variant cpp

Observations:

  • no need to copy contents from a to tmp
  • no need to copy contents from b to tmp
  • a‘s copy inside tmp is no longer needed at the end

We need:

  • a way to move the internal states of objects
  • a way to express “this is object is temporary/can be recycled”
  • to overload funtions / constructors / … for such temporaries

std::move

After using std::move we expect to have some perfomance gain if T is cheaply movable.

Almost all standard containers are cheap to move (std::array is not).

template<typename T>
void foo(T& a, T& b) {
    auto tmp = std::move(a);
    a = std::move(b);
    b = std::move(tmp);
}

lvalue and rvalue

lvalue = expression of which we can take its memory address

rvalue = expression of which we cannot take its memory address

Original meaning: (l/r) values on (left/right) hand side of assignment

lvalue vs rvalue cpp
auto x = std::make_unique<int>(5);
std::unique_ptr<int> y;
y = std::move(x);
unique ptr move cpp

rvalue references

lvalue references:

  • T& – bind to non-const lvalues of type T only
  • T const& – bind to const lvalues and rvalues of type T

rvalue references:

  • T&& – bind to rvalues of type T only

std::move and rvalue

So now we can say that std::move casts an expression to an rvalue.

void foo(int& x);
void bar(int const& x);
void baz(int&& x);

int i = 0;

foo(i);           // OK
foo(std::move(i)) // ERROR: lvalue ref cannot bind to rvalue

bar(i);           // OK
bar(move(i));     // OK

baz(i);           // ERROR: rvalue ref cannot bind to lvalue
baz(std::move(i));// OK

Overview of Special Member Functions

class T {
    T();                            // Default Constructor

    T(std::initializer_list<...>);  // Initializer List Constructor

    ~T();                           // Destructor

    T(T const&);                    // Copy Constructor
    T& operator=(T const&);         // Copy Assignment Operator

    T(T&&);                         // Move Constructor
    T& operator=(T&&);              // Move Assignment Operator
}

Reference:

https://hackingcpp.com/cpp/lang/move_semantics.html

Other cpp articles from my site:

https://mateuszrzeczyca.pl/c-and-smart-pointers-my-notes/

https://mateuszrzeczyca.pl/c-and-shallow-copy-vs-deep-copy/

C++ Graphics Software Engineer