C++右值引用
一、左值、右值
1.1 什么是左值、右值
1 | |
简单来说,左值就是等号左边的值,可以取地址,也就是这里的 a;右值就是等号右边的值,不能够取地址,也就是这里的 5。
a可以通过&取地址,位于等号左边,所以a是左值5位于等号右边,5没法通过&取地址,所以5是个右值
再看一个例子:
1 | |
- 同样的,
a可以通过&取地址,位于等号左边,所以a是左值 A()是个临时值,没法通过&取地址,位于等号右边,所以A()是个右值
1.2 什么是左值引用、右值引用
引用本质是别名,可以通过引用修改变量的值,传参时传引用可以避免拷贝,其实现原理和指针类似。
1.2.1 左值引用
左值引用能指向左值,不能指向右值的就是左值引用:
1 | |
引用是变量的别名,由于右值没有地址,没法被修改,所以左值引用无法指向右值。
但是,const左值引用是可以指向右值的:
1 | |
const左值引用不会修改指向值,因此可以指向右值,这也是为什么要使用const &作为函数参数的原因之一,如std::vector的push_back:
1 | |
如果没有const,vec.push_back(5)这样的代码就无法编译通过了。
1.2.2 右值引用
再看下右值引用,右值引用的标志是 &&,顾名思义,右值引用专门为右值而生,可以指向右值,不能指向左值:
1 | |
1.2.3 让右值引用指向左值
通过 std::move 可以使右值引用指向左值:
1 | |
注意,std::move 的唯一作用是将左值强制转化为右值,源码如下:
1 | |
可见, 单纯的 std::move(xxx) 不会有性能提升。
同样的,右值引用能指向右值,本质上也是把右值提升为一个左值,并定义一个右值引用通过 std::move 指向该左值:
1 | |
1.3 左值引用、右值引用本身是左值还是右值
被声明出来的左、右值引用都是左值。 因为被声明出的左右值引用是有地址的,也位于等号左边。
1 | |
- 从性能上讲,左右值引用没有区别,传参使用左右值引用都可以避免拷贝
- 右值引用可以直接指向右值,也可以通过
std::move指向左值;而左值引用只能指向左值(const 左值引用也能指向右值) - 作为函数形参时,右值引用更灵活。虽然 const 左值引用也可以做到左右值都接受,但它无法修改,有一定局限性
1 | |
二、右值引用的应用
2.1 实现移动语义
见 C++11新特性(一)。
2.2 完美转发
C++右值引用
http://example.com/2026/05/10/C++右值引用/