C++ 中的右值引用与移动语义
C++11 引入了右值引用(rvalue reference)和移动语义(move semantics),大幅优化了对象的拷贝效率。本文将详细讲解其原理与示例。
一、左值与右值
- 左值:有名称、可取地址的变量
- 右值:没有名称的临时对象或返回值
cpp
int x = 5; // x 是左值
int y = x; // x 被拷贝
int z = 10 + 20; // 10+20 是右值
二、右值引用
右值引用使用 && 声明,可以绑定到右值:
cpp
void print(int &&x) {
std::cout << x << "\n";
}
int main() {
print(5); // OK
// int a = 10; print(a); // 错误,a 是左值
}
三、移动语义
移动语义通过 std::move 将资源从一个对象转移到另一个对象,避免不必要的拷贝:
cpp
#include <iostream>
#include <vector>
int main() {
std::vector<int> v1 = {1, 2, 3, 4};
std::vector<int> v2 = std::move(v1); // 移动资源
std::cout << "v1 size: " << v1.size() << "\n"; // 0
std::cout << "v2 size: " << v2.size() << "\n"; // 4
}
四、移动构造与移动赋值
自定义类也可以实现移动构造和移动赋值:
cpp
class MyClass {
int* data;
public:
MyClass(int n) : data(new int[n]) {}
~MyClass() { delete[] data; }
// 移动构造
MyClass(MyClass&& other) noexcept : data(other.data) {
other.data = nullptr;
}
// 移动赋值
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
other.data = nullptr;
}
return *this;
}
};
总结
-
右值引用允许函数接收临时对象
-
std::move 实现资源转移,减少拷贝开销
-
移动构造和移动赋值可以优化类的性能