skip to content
Mehdi Mehdikhani
Table of Contents

Move semantics is one of those C++11 features that sounds scary but is actually pretty straightforward once you underestand it.

What std::move Actually Does

Here’s the thing that confused me for a long time: std::move doesn’t actually move anything. It’s just a cast. All it does is convert whatever you pass to it into an rvalue reference. The actual “moving” happens in the move constructor or move assignment operator of the object.

std::string original = "Hello";
std::string moved = std::move(original); // std::move just casts to rvalue reference
// The actual move happens in std::string's move constructor

After this, original is in a valid but unspecified state. You can still call methods on it, but you shouldn’t assume what it contains.

Why This Matters

Think about a vector with a million elements. Without move semantcs, every time you returned it from a function or pass it around, you’d copy all million elements. With move semantics, you can just “steal” the internal pointer and leave the original object empty.

// Without move semantics - expensive copy
std::vector<int> createBigVector() {
std::vector<int> vec(1000000, 42);
return vec; // expensive copy before C++11
}
// With move semantics - just steal the resources
std::vector<int> createBigVector() {
std::vector<int> vec(1000000, 42);
return vec; // Compiler automatically uses move semantics
}

The compiler is actually smart enough to use move semantics automatically in many cases (like returning from functions), but sometimes you need std::move.

When I Actually Use std::move

Most of the time, I use std::move in these situations:

  1. Moving into containers: When I want to transfer ownership of an expensive object into a vector or other container:
std::vector<std::string> names;
std::string long_name = "This is a very long text that I do not want to copy";
names.push_back(std::move(long_name)); // Transfer ownership, no copy
// long_name is now empty, but names[0] has the string!
  1. In constructors and assignment operators: When implementing my own classes that manage resources:
class MyClass {
std::vector<int> data_;
public:
MyClass(std::vector<int> data) : data_(std::move(data)) {}
// Move the parameter into the member variable
};
  1. Swapping without copies: Though std::swap already does this internally:
std::string a = "first";
std::string b = "second";
std::string temp = std::move(a);
a = std::move(b);
b = std::move(temp);

The Rule I Follow

I only use std::move when I’m done with an object and want to transfer its resources to something else. If I might need the object later, I don’t move it. Simple :)

The performance gains can be significant for big and expensive objects like containers, strings, or smart pointers. For simple types like integers, move and copy are identical, so it doesn’t matter.

One last thing: don’t std::move the return value from functions. The compiler already optimizes that case, and being explicit about it can actually prevent the optimization.