C++ Move Semantics
In this page:
What is Move Semantics?
Move semantics lets the compiler transfer ownership of a resource -- like heap-allocated memory inside a std::vector or std::string -- from a temporary object directly into a new one, instead of performing a full deep copy. For large objects, this turns an O(n) copy into an O(1) pointer swap.
Example: What is Move Semantics?
#include <iostream>
#include <vector>
int main() {
std::vector<int> source = {1, 2, 3};
std::vector<int> destination = std::move(source);
std::cout << destination.size() << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
The std::move Function
std::move() doesn't physically move any data by itself -- it's purely a cast that tells the compiler "treat this lvalue as an rvalue," making it eligible to be moved from. The actual transfer of ownership happens inside whatever move constructor or move assignment operator subsequently receives it.
Example: The std::move Function
#include <iostream>
#include <string>
#include <utility>
int main() {
std::string a = "Hello";
std::string b = std::move(a);
std::cout << b << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Move Constructor
A move constructor takes ownership of a temporary object's internal resources (like a raw pointer to heap memory) by copying that pointer into the new object, then setting the temporary's own pointer to nullptr so its destructor won't accidentally free memory the new object now owns.
Example: Move Constructor
#include <iostream>
class Buffer {
public:
int *data;
Buffer(int val) { data = new int(val); }
Buffer(Buffer &&other) noexcept {
data = other.data;
other.data = nullptr;
}
~Buffer() { delete data; }
};
int main() {
Buffer a(5);
Buffer b(std::move(a));
std::cout << *b.data << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Move Assignment Operator
The move assignment operator first releases whatever resources the target object currently holds (to avoid a leak), then steals the source object's resources the same way a move constructor does -- this is why move assignment is typically written to reuse the move constructor's logic.
Example: Move Assignment Operator
#include <iostream>
class Buffer {
public:
int *data;
Buffer(int val) { data = new int(val); }
Buffer &operator=(Buffer &&other) noexcept {
delete data;
data = other.data;
other.data = nullptr;
return *this;
}
~Buffer() { delete data; }
};
int main() {
Buffer a(5), b(10);
b = std::move(a);
std::cout << *b.data << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Performance Benefits
For types holding large buffers -- strings, vectors, and similar containers -- move semantics avoids the deep copy those types would otherwise require, which matters most when returning large objects from functions or storing them in containers that resize and relocate elements.
Example: Performance Benefits
#include <iostream>
#include <string>
std::string buildGreeting() {
std::string result = "Hello, World!";
return result;
}
int main() {
std::string message = buildGreeting();
std::cout << message << std::endl;
return 0;
}
Login to try C/C++/Java/PHP code in the editor
Chapter Quiz — Complete all 9 topics to unlock
0/9 topics done
Complete these topics first: