The Runtime Theory
C++

Move Semantics and Rvalue References

How std::move and rvalue references eliminate unnecessary copies, and when move constructors are called.

The Runtime Theory Team1 min read
▸ On this page

Move Semantics and Rvalue References

C++11 introduced move semantics — a way to transfer ownership of resources instead of copying them. This is one of the biggest performance improvements in modern C++.

Lvalues vs Rvalues

An lvalue is an expression that identifies an object (you can take its address):

cpp
int x = 42;  // x is an lvalue
int& ref = x;  // ref is an lvalue reference (can't bind to rvalue)

An rvalue is a temporary value (you can't take its address):

cpp
int y = x + 1;  // (x + 1) is an rvalue, 42 is an rvalue
int&& rref = 42;  // rref is an rvalue reference

std::move

std::move doesn't actually move anything — it casts an lvalue to an rvalue, enabling the move constructor:

cpp
std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = std::move(v1);
// v1 is now empty — its internal buffer was moved to v2
// No elements were copied; just a pointer assignment

Move Constructor and Move Assignment

cpp
class MyString {
  char* data;
  size_t len;
 
public:
  // Move constructor
  MyString(MyString&& other) noexcept
    : data(other.data), len(other.len) {
    other.data = nullptr;  // take ownership
    other.len = 0;
  }
 
  // Move assignment
  MyString& operator=(MyString&& other) noexcept {
    if (this != &other) {
      delete[] data;       // free my old data
      data = other.data;   // take ownership
      len = other.len;
      other.data = nullptr;
      other.len = 0;
    }
    return *this;
  }
};

When Move Is Called

cpp
std::vector<int> makeVector() {
  std::vector<int> v = {1, 2, 3};
  return v;  // move (or copy elision in C++17+)
}
 
std::vector<int> v = makeVector();  // move constructor called
v.push_back(4);  // might reallocate and move existing elements

Move semantics eliminates expensive deep copies by transferring ownership of underlying resources (heap memory, file descriptors, etc.).

Perfect Forwarding

std::forward preserves the value category (lvalue/rvalue) when passing arguments through generic wrapper functions. This is used in std::make_unique, std::make_shared, and std::thread.

Not started

Sign in to save your learning progress.

Sign in to save