1. C++11 右值引用与移动语义:从理论到实战
C++11 引入的右值引用和移动语义彻底改变了 C++ 程序员处理对象生命周期和资源管理的方式。作为现代 C++ 最核心的特性之一,理解这些概念对编写高效代码至关重要。
1.1 左值与右值的本质区别
1.1.1 左值(Lvalue)详解
左值可以简单理解为"有名字的持久对象",但更准确的定义是:
- 具有明确存储位置(可获取地址)
- 生命周期超出单个表达式
- 可被多次引用
典型左值示例:
cpp复制int x = 42; // x是左值
int* p = &x; // 可以获取地址
int& r = x; // 可被引用
vector<int> v;
v[0] = 10; // 下标操作返回左值引用
1.1.2 右值(Rvalue)深度解析
右值代表"临时对象或纯值",关键特征:
- 没有持久存储位置(不能取地址)
- 生命周期通常限于当前表达式
- 只能被绑定一次
常见右值场景:
cpp复制int x = 10 + 20; // 10+20是右值
string s = "hello" + "world"; // 字符串连接产生右值
vector<int> getVec() { return {1,2,3}; }
auto v = getVec(); // 函数返回的临时对象是右值
1.1.3 值类别扩展:泛左值与纯右值
C++标准中更精确的分类:
| 类别 | 特性 | 示例 |
|---|---|---|
| 泛左值 | 有身份(identity) | 变量、函数返回值 |
| 纯右值 | 仅代表值 | 字面量、临时对象 |
实际开发中只需记住:能取地址的是左值,否则基本是右值。
1.2 右值引用的设计哲学
1.2.1 传统拷贝的性能瓶颈
考虑字符串类的拷贝构造:
cpp复制class String {
char* data;
public:
String(const String& other) {
data = new char[strlen(other.data)+1];
strcpy(data, other.data); // 深拷贝!
}
};
每次拷贝都需要分配新内存并复制内容,对于临时对象这种拷贝完全浪费。
1.2.2 右值引用的解决方案
右值引用(T&&)专门用于识别临时对象:
cpp复制String(Str
