2y ago · Mar 10, 2024 2:20 PM
Move semantics (introduced in C++11 and refined in C++14/17/20) is one of the most important concepts for writing high-performance C++ software by eliminating unnecessary deep copies.
1. Lvalues vs Rvalues:
- Lvalue (Left-hand value): An expression that has an identifiable memory location and persists beyond a single expression (e.g. named variables).
- Rvalue (Right-hand value): A temporary value that does not persist beyond the expression that creates it (e.g. literals, function returns ).
2. Implementing the Move Constructor & Move Assignment Operator:
3. What actually does:
does not move anything at runtime! It is simply an unconditional that converts an lvalue into an rvalue reference, allowing the compiler to select the move constructor over the copy constructor.
1. Lvalues vs Rvalues:
- Lvalue (Left-hand value): An expression that has an identifiable memory location and persists beyond a single expression (e.g. named variables
CODE
int x = 10;- Rvalue (Right-hand value): A temporary value that does not persist beyond the expression that creates it (e.g. literals
CODE
42 CODE
std::string("temp")2. Implementing the Move Constructor & Move Assignment Operator:
CPP
#include <iostream>
#include <utility>
#include <cstring>
class DynamicBuffer {
private:
char* data;
size_t size;
public:
// Constructor
DynamicBuffer(size_t s) : size(s), data(new char[s]) {
std::memset(data, 0, size);
}
// Destructor (RAII)
~DynamicBuffer() {
delete[] data;
}
// Copy Constructor (Deep Copy - O(N))
DynamicBuffer(const DynamicBuffer& other) : size(other.size), data(new char[other.size]) {
std::memcpy(data, other.data, size);
std::cout << "[Copy Constructor] Deep copy performed
";
}
// Move Constructor (Shallow Resource Transfer - O(1))
DynamicBuffer(DynamicBuffer&& other) noexcept : data(other.data), size(other.size) {
other.data = nullptr; // Leave source object in valid empty state
other.size = 0;
std::cout << "[Move Constructor] Pointer ownership stolen (O(1))
";
}
// Move Assignment Operator
DynamicBuffer& operator=(DynamicBuffer&& other) noexcept {
if (this != &other) {
delete[] data; // Free existing resource
data = other.data;
size = other.size;
other.data = nullptr;
other.size = 0;
std::cout << "[Move Assignment] Resource swapped
";
}
return *this;
}
};3. What
CODE
std::move CODE
std::move CODE
static_cast<T&&> CPP
DynamicBuffer buf1(1024 * 1024); // 1MB buffer
DynamicBuffer buf2 = std::move(buf1); // Calls move constructor, zero memory allocation!
KronoDev - Keep coding, keep learning
The following users thanked KronoDev for this post: