C++ 新特性 | C++ 11 | 左值、右值与将亡值
文章目录
- 一、左值、右值与将亡值
- 1、左值 (lvalue)
- 2、右值 (rvalue)
- 3、将亡值 (xvalue)
- 4、左值引用 (lvalue reference)
- 5、右值引用 (rvalue reference)
- 6、右值引用本身是左值
- 6.1、核心概念
- 6.2、示例
一、左值、右值与将亡值
1、左值 (lvalue)
- 是什么:能取地址、有名字的值(比如变量)。
- 特点:可以放在等号左边(比如
a = 10
)。 - 例子:
int a = 10; // a是左值
2、右值 (rvalue)
- 是什么:临时值,不能取地址(比如字面量、临时结果)。
- 特点:只能放在等号右边(比如
10 = a
是错的)。 - 例子:
int b = 20; // 20是右值 int c = a + b; // (a + b)的结果是右值
3、将亡值 (xvalue)
- 是什么:介于左值和右值之间,通常是“即将被移动”的值。
- 特点:可以被右值引用绑定,资源会被“偷走”(移动语义)。
- 例子:
std::string s1 = "Hello"; std::string s2 = std::move(s1); // s1变成将亡值,内容被移动到s2
注意:将亡值是右值的一种。
4、左值引用 (lvalue reference)
- 是什么:用
&
声明的引用,只能绑定左值。 - 用途:别名,修改原变量。
- 例子:
int a = 10; int &ref = a; // ref是a的别名 ref = 20; // 修改a的值
5、右值引用 (rvalue reference)
- 是什么:用
&&
声明的引用,只能绑定右值(或将亡值)。 - 用途:实现移动语义(避免拷贝,直接“偷”资源)。
- 例子:
std::string s1 = "Hello"; std::string s2 = std::move(s1); // std::move(s1)返回右值引用
6、右值引用本身是左值
在C++中,右值引用(
T&&
)变量本身实际上是一个左值,这看起来似乎矛盾,但理解这一点对掌握移动语义和完美转发至关重要。
6.1、核心概念
- 右值引用的本质:
- 右值引用是 可以绑定到右值 的引用类型
- 但一旦绑定后,这个引用变量 本身是一个具名对象,因此是左值
- 为什么是左值?:
void foo(int&& rref) {// rref 在这里是左值,因为它:// 1. 有名字 (rref)// 2. 可以取地址 (&rref)// 3. 可以出现在赋值左侧 }
6.2、示例
void process(int&) { std::cout << "lvalue\n"; }
void process(int&&) { std::cout << "rvalue\n"; }template<typename T>
void relay(T&& arg) {process(arg); // 总是调用左值版本process(std::forward<T>(arg)); // 根据原始类型调用
}int main() {int x = 10;relay(x); // 传入左值relay(20); // 传入右值
}
输出:
lvalue
lvalue
lvalue
rvalue
一句话总结:
- 左值:有名字的变量;右值:临时的值;将亡值:快被移动的值。
- 左值引用 (
&
):操作原变量;右值引用 (&&
):高效“偷”资源。