移动语义与右值引用
左值/右值、std::move、移动构造/赋值、完美转发 forward
移动语义与右值引用
C++11 引入移动语义——不再拷贝数据,而是"窃取"资源的所有权。这是现代 C++ 最重要的性能优化。
学完本章你将: 理解左值/右值、std::move、移动构造/赋值、完美转发。
左值与右值
cpp
int x = 42; // x 是左值(有名字、可取地址)
int y = x + 1; // x + 1 是右值(临时值、不可取地址)
int &ref = x; // 左值引用绑定左值
int &&rref = 42; // 右值引用绑定右值
// int &&rref2 = x; // ❌ 右值引用不能绑定左值
std::move —— 左值转右值
cpp
#include <utility>
#include <string>
int main() {
std::string s1 = "Hello World";
std::string s2 = s1; // 拷贝——s1 不变
std::string s3 = std::move(s1); // 移动——s1 被"掏空"(高效!)
// 移动后:s1 处于"有效但未指定"状态,不应再使用
return 0;
}
⚠️
std::move不移动任何东西——它只是把左值转换成右值引用。真正的"移动"发生在移动构造函数或移动赋值运算符中。
移动构造与移动赋值
cpp
class Buffer {
int *data;
size_t size;
public:
// 移动构造:窃取 other 的资源
Buffer(Buffer &&other) noexcept
: data(other.data), size(other.size) {
other.data = nullptr; // 让 other 安全析构
other.size = 0;
}
// 移动赋值
Buffer &operator=(Buffer &&other) noexcept {
if (this != &other) {
delete[] data; // 释放自己的
data = other.data; // 窃取 other 的
size = other.size;
other.data = nullptr;
other.size = 0;
}
return *this;
}
~Buffer() { delete[] data; }
};
完美转发
cpp
template <typename T>
void wrapper(T &&arg) {
// std::forward 保持参数的左值/右值属性
target(std::forward<T>(arg));
}