Question
In C++, what is std::move()?
What does it actually do, and in what situations should it be used?
A clear explanation with practical examples would be helpful, especially for understanding how it relates to move semantics and object ownership.
Short Answer
By the end of this page, you will understand that std::move() does not move anything by itself. Instead, it converts an object into an rvalue so that move constructors or move assignment operators may be used. You will also learn when using std::move() is appropriate, when it is unnecessary or harmful, and how it appears in real C++ code.
Concept
std::move() is a standard library utility in C++ that enables move semantics.
At a high level, move semantics let a program transfer ownership of expensive resources—such as heap memory, file handles, or buffers—from one object to another without making a full copy.
What std::move() really does
std::move() does not physically move data.
It simply casts its argument to an rvalue reference type, which signals:
- "This object may be treated as a temporary."
- "Its resources can be taken from, if the type supports moving."
A simplified idea looks like this:
template <class T>
constexpr typename std::remove_reference<T>::type&& move(T&& t) noexcept;
That means std::move(x) says: treat x as something that can be moved from.
Why this matters
Before C++11, objects were mostly copied. Copying can be expensive for types like:
std::string
Mental Model
Think of an object as a person holding a backpack.
- Copying means making a brand-new backpack with the same contents.
- Moving means handing the existing backpack to someone else.
std::move()is not the handoff itself.- It is more like saying: "I am done needing this backpack in its current state; you may take it."
After that handoff, the original person is still there, but you should not expect them to still have the backpack contents.
This model helps explain why std::move() is just permission to move, not the move itself.
Syntax and Examples
Basic syntax
std::move(object)
Include the header:
#include <utility>
Example: moving a string
#include <iostream>
#include <string>
#include <utility>
int main() {
std::string source = "Hello, world!";
std::string target = std::move(source);
std::cout << "target: " << target << '\n';
std::cout << "source: " << source << '\n';
}
What this means
sourceis a named variable, so it is normally an lvalue.std::move(source)converts it to an rvalue.targetcan now use the move constructor ofstd::string.
Step by Step Execution
Consider this example:
#include <iostream>
#include <string>
#include <utility>
int main() {
std::string a = "cat";
std::string b = std::move(a);
std::cout << "a: " << a << '\n';
std::cout << "b: " << b << '\n';
}
Step-by-step
1. Create a
std::string a = "cat";
aowns the characters"cat".ais a named object, so it is an lvalue.
2. Call std::move(a)
std::string b = std::move(a);
- casts to an rvalue reference.
Real World Use Cases
Returning large objects efficiently
Modern C++ often returns objects by value. Compilers frequently optimize this well, but move semantics also help when ownership is transferred.
std::vector<int> build_data() {
std::vector<int> data = {1, 2, 3, 4};
return data;
}
In many cases, you do not need to write std::move(data) here because return value optimization may apply.
Transferring ownership of resources
std::unique_ptr depends on move semantics.
std::unique_ptr<File> open_file();
A unique pointer cannot be copied, so moving is how ownership is passed safely.
Inserting expensive objects into containers
std::vector<std::string> logs;
std::string message = "Request completed";
logs.push_back(std::move(message));
This avoids an unnecessary copy when message is no longer needed.
Real Codebase Usage
In real projects, std::move() is commonly used in a few predictable patterns.
1. Moving from local parameters into members
class Config {
public:
Config(std::string path) : path_(std::move(path)) {}
private:
std::string path_;
};
This is common because the parameter is a local object that is about to go out of scope.
2. Transferring ownership with smart pointers
void set_logger(std::unique_ptr<Logger> logger) {
logger_ = std::move(logger);
}
This makes ownership transfer explicit.
3. Container insertion
items.push_back(std::move(item));
Used when item will not be needed in its old state afterwards.
4. Move constructors and move assignment operators
class Buffer {
public:
(Buffer&& other)
: (other.data_), (other.size_) {
other.data_ = ;
other.size_ = ;
}
Buffer& =(Buffer&& other) {
( != &other) {
[] data_;
data_ = other.data_;
size_ = other.size_;
other.data_ = ;
other.size_ = ;
}
*;
}
:
* data_ = ;
std:: size_ = ;
};
Common Mistakes
1. Thinking std::move() always moves
It only casts to an rvalue. If the type has no move constructor or move assignment operator, a copy may still happen.
MyType a;
MyType b = std::move(a); // may copy if MyType is not movable
2. Using the moved-from object as if nothing happened
Broken idea:
std::string name = "Alice";
std::string other = std::move(name);
if (name == "Alice") {
// Wrong assumption
}
Avoid this by only:
- destroying the moved-from object
- assigning a new value to it
- using operations that are guaranteed safe for its valid-but-unspecified state
3. Moving from an object too early
std::string s = "hello";
process(std::move(s));
std::cout << s; // maybe valid, but old content should not be assumed
Only move when you are truly done with the original value.
4. Using std::move() on const objects
Comparisons
std::move() vs actual moving
| Concept | What it does |
|---|---|
std::move(x) | Casts x to an rvalue so moving is allowed |
| Move constructor / move assignment | Actually transfers resources |
| Copy constructor / copy assignment | Duplicates resources |
Copy vs move
| Operation | Source object after operation | Cost | Typical use |
|---|---|---|---|
| Copy | Unchanged | Often higher | When both objects need the same value |
| Move | Valid but unspecified | Often lower |
Cheat Sheet
Quick reference
Include
#include <utility>
Basic use
std::move(x)
What it does
- Casts
xto an rvalue reference - Does not move by itself
- Enables move constructor / move assignment selection
Use it when
- you are done with an object's current value
- you want to transfer ownership
- you are moving into a container or member
- you are working with move-only types like
std::unique_ptr
Do not use it when
- you still need the original value unchanged
- you are returning a local variable by value in simple cases
- the source object is
constand you expect a real move
Safe assumptions after move
- object is valid
- object can be destroyed
- object can be assigned a new value
- old content should not be relied on
Common pattern
class {
:
(std::string name) : (std::(name)) {}
:
std::string name_;
};
FAQ
What is std::move() in simple terms?
It tells C++ that an object may be treated as temporary, so its resources can be transferred instead of copied.
Does std::move() actually move data?
No. It only casts an object to an rvalue reference. The actual move happens only if a move operation is available.
When should I use std::move()?
Use it when you no longer need an object's current value and want to transfer its contents or ownership to another object.
Is it safe to use an object after std::move()?
Yes, but only carefully. The object remains valid, but its value is unspecified. You should not assume it still contains the old data.
Why doesn't std::move() work well with const objects?
Because moving usually modifies the source object. A const object cannot be modified, so move operations often cannot be used and copying happens instead.
Should I use std::move() when returning a local variable?
Usually no. Returning the local variable directly often allows better optimization and is simpler.
Why do I need std::move() for std::unique_ptr?
Because cannot be copied. Ownership must be transferred with move semantics.
Mini Project
Description
Create a small C++ program that models transferring ownership of a resource using move semantics. This project demonstrates when std::move() is useful and what happens to the source object after the transfer. It also shows a realistic case where copying should be disabled but moving should be allowed.
Goal
Build a move-only FileHandle-style class and transfer ownership from one object to another using std::move().
Requirements
[ "Create a class that owns a resource represented by a string or integer handle.", "Disable copying so the resource cannot be duplicated accidentally.", "Implement a move constructor and move assignment operator.", "Move one object into another using std::move().", "Print the state before and after the move to show ownership transfer." ]
Keep learning
Related questions
Basic Rules and Idioms for Operator Overloading in C++
Learn the core rules, syntax, and common idioms for operator overloading in C++, including member vs non-member operators.
C++ Base Class Constructor Rules Explained
Learn how C++ base class constructors are called from derived classes, including order, syntax, defaults, and common mistakes.
C++ Casts Explained: C-Style Cast vs static_cast vs dynamic_cast
Learn the difference between C-style casts, static_cast, and dynamic_cast in C++ with clear examples, safety rules, and real usage tips.