C++ 右值引用与 const 关键字
作者:互联网
C++11 新增了另一种引用:右值引用(rvalue reference),这种引用可指向右值,是使用 &&
声明的。使用右值引用可以减少复制操作,延长临时对象生命周期,提升程序性能。它一般被用来实现移动语义和完美转发,将 const
关键字用于右值引用的场景不多,这里来总结一下 const
右值引用的特性,对其是否具有实际应用价值不做讨论。右值引用必须在创建的同时进行初始化,且只能使用右值进行初始化,可将 const
关键字用于右值引用,如下所示:
//声明并初始化常规右值引用变量 |
|
int && rrx = 55; |
|
//将const关键字用于右值引用变量,以下几种为等效表示 |
|
const int && crrx = 55; |
|
int const && crrx = 55; |
在 Microsoft Visual Studio 中连续多个 const
会被编译器解释成一个,即 const const const const int &&
与 const int &&
等效,除此之外,const int const &&
在 Microsoft Visual Studio 中也与 const int &&
等效,而 int && const
在 QT minGW 中将会报错,在 Microsoft Visual Studio 中与 int &&
等效。
常规右值引用与 const
右值引用的特性如下:
- 类型为
int &&
的引用只能用来引用右值,不能用来引用左值,后面可修改其值。可将类型为int
的非左值(比如字面常量100
、多项表达式1+50*2
、函数的int
返回值)、类型不是int
但可转换为int
的非左值(比如多项表达式1.0+50.0*2.0
、字面常量100.0
、函数的double
返回值)在初始化时赋给rrx
。变量初始化完成后,其地址就固定不变,其表现与int
类型变量一致,右值引用变量自身属于左值。 - 类型为
const int &&
的引用也只能用来引用右值,不能用来引用左值,但后面不可修改其值。可将类型为int
的非左值(比如字面常量100
、多项表达式1+50*2
、函数的int
返回值)、类型不是int
但可转换为int
的非左值(比如多项表达式1.0+50.0*2.0
、字面常量100.0
、函数的double
返回值)在初始化时赋给crrx
。变量初始化完成后,其地址就固定不变,其表现与const int
类型变量一致,自身也属于左值。
常规右值引用变量的初始化用法如下:
//初始化方式一:字面常量 |
|
int && rrx = 100; |
|
int && rrx = 100.0; |
|
//初始化方式二:多项表达式 |
|
int && rrx = 1+50*2; |
|
int && rrx = 1.0+50.0*2.0; |
|
//初始化方式二:函数返回值 |
|
int && rrx = abs(10); |
|
int && rrx = sqrt(10.0); |
右值引用在部分情况下会生成临时变量(一个典型例子是使用字面常量右值如 100
来初始化右值引用变量),然后将右值引用变量作为该临时变量的别名,这与 const
左值引用十分相似,但与之不同的是:const
左值引用变量初始化完成后其值就无法被修改(权限为只读),右值引用变量初始化完成后其值仍可修改(权限为可读可写)。在另一些情况下,右值引用可以延长已有临时变量的生命周期,减少复制操作的次数(一个典型例子是使用函数返回的类对象来初始化右值引用变量,在关闭编译器优化的情况下可以将本需 2 次的复制操作减少为 1 次)。
被 const
关键字修饰的右值引用变量初始化用法如下,与常规右值引用变量的区别仅在于它们的可修改属性不同。
//初始化方式一:字面常量 |
|
const int && crrx = 100; |
|
const int && crrx = 100.0; |
|
//初始化方式二:多项表达式 |
|
const int && crrx = 1+50*2; |
|
const int && crrx = 1.0+50.0*2.0; |
|
//初始化方式二:函数返回值 |
|
const int && crrx = abs(10); |
|
const int && crrx = sqrt(10.0); |
将初始化时 int &&
与 const int &&
可接受的形式列个表,如下,需要注意的是:可以将右值引用变量用于初始化左值引用变量,但不可将左值引用变量用于初始化右值引用变量,因为右值引用变量自身属于左值。
初始化时可接受的形式 | int && 类型 |
const int && 类型 |
---|---|---|
int 变量 |
不可以 | 不可以 |
const int 变量 |
不可以 | 不可以 |
int & 变量 |
不可以 | 不可以 |
const int & 变量 |
不可以 | 不可以 |
int && 变量 |
不可以 | 不可以 |
const int && 变量 |
不可以 | 不可以 |
形如 100 的 int 字面常量 |
可以 | 可以 |
形如 1+50*2 的 int 多项表达式 |
可以 | 可以 |
返回类型为 int 的函数返回值 |
可以 | 可以 |
形如 100.0 可转换为 int 的字面常量 |
可以 | 可以 |
形如 1.0+50.0*2.0 可转换为 int 的多项表达式 |
可以 | 可以 |