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 的多项表达式 |
可以 | 可以 |
C++ 右值引用与 const 关键字的更多相关文章
- c/c++ 右值引用,forward关键字
c++ forward关键字 forward的由来:模板函数中的推导类型,作为另一函数的参数时,不管实参是什么类型,作为另一个参数的实参时,都变成了左值.因为C++里规定函数的形参就是左值,不过调用侧 ...
- c++ 右值引用,move关键字
c++ move关键字 move的由来:在 c++11 以前存在一个有趣的现象:T& 指向 lvalue (左传引用), const T& 既可以指向 lvalue 也可以指向 rv ...
- C++ 左值引用与 const 关键字
左值引用是已定义的变量的别名,其主要用途是用作函数的形参,通过将左值引用变量用作参数,函数将使用原始数据,而不是副本.引用变量必须在声明时同时初始化,可将 const 关键字用于左值引用,如下所示: ...
- C++ 右值引用与一级指针
将右值引用用于一级指针,在初始化时等号右边必须为右值,有以下几种用法: //方式一:引用一级指针,常规用法 int a = 5; int * &&rrpa = &a; //右值 ...
- [转载] C++11中的右值引用
C++11中的右值引用 May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移动语义std::move() 右值引用和右值的关系 完美转发 引用折叠推导 ...
- C++11中的右值引用
原文出处:http://kuring.me/post/cpp11_right_reference May 18, 2015 移动构造函数 C++98中的左值和右值 C++11右值引用和移动语义 强制移 ...
- c++11之右值引用
本文大部分来自这里,并不是完全着行翻译,如有不明白的地方请参考原文. 在c++中,创建临时对象的开销对程序的影响一直很大,比如以下这个例子: String getName(){ return “Kia ...
- 【C/C++开发】C++11:左值引用VS右值引用
左值引用VS右值引用 左值引用对于一般的C++程序员再熟悉不过,但对于右值引用(C++0X新特性),就稍微有点不知所云 左值VS右值 在定义变量的时候,经常会用到左值和右值,比如:int a = 1; ...
- C++11右值引用和std::move语句实例解析
关键字:C++11,右值引用,rvalue,std::move,VS 2015 OS:Windows 10 右值引用(及其支持的Move语意和完美转发)是C++0x将要加入的最重大语言特性之一.从实践 ...
随机推荐
- 2022-7-11第五组 pan小堂 js基础
##为何学习 JavaScript? ###JavaScript 是 web 开发者必学的三种语言之一: HTML 定义网页的内容 CSS 规定网页的布局 JavaScript 对网页行为进行编程 在 ...
- 迭代器和增强for循环
iterator 迭代:即Collection集合元素的通过获取方法,在获取元素之前先要判断集合中有没有元素,如果有就把这个元素取出来,然后在判断,如果还有就再去除卡u,一直把集合中的所有元素全部拿出 ...
- 奇技淫巧玄妙无穷| M1 mac os(苹果/AppleSilicon)系统的基本操作和设置
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_191 最近有个朋友跟我说,说他新入职了一家公司,公司还不错,给他配了一台Mac,但是呢他以前一直在Windows环境下开发,对Ma ...
- Vue路由器的hash和history两种工作模式 && Vue项目编译部署
1 # 一.Vue路由器的两种工作模式 2 # 1.对于一个uri来说,什么是hash值? 井号及其后面的内容就是hash值. 3 # 2.hash值不会包括含在HTTP请求中,即:hash值不会带给 ...
- 【springcloud】环境搭建与Rest使快速上手
SpringCloud环境搭建 --- Rest使用 个人主页:https://www.cnblogs.com/xbudian/ 今天来到SpringCloud的学习,我们从spring boot微服 ...
- BZOJ4580/Luogu3147 [Usaco2016 Open]248
amazing #include <iostream> #include <cstdio> #include <cstring> #include <algo ...
- Kotlin协程解析系列(上):协程调度与挂起
vivo 互联网客户端团队- Ruan Wen 本文是Kotlin协程解析系列文章的开篇,主要介绍Kotlin协程的创建.协程调度与协程挂起相关的内容 一.协程引入 Kotlin 中引入 Corout ...
- 从C过渡到C++——换一个视角深入数组[初始化](1)
从C过渡到C++--换一个视角深入数组[初始化](1) 目录 从C过渡到C++--换一个视角深入数组[初始化](1) 数组的初始化 从C入手 作用域 代码块作用域 文件作用域 原型作用域 函数作用域 ...
- MySQL查询关键数据方法
MySQL查询关键数据方法 操作表的SQL语句补充 1.修改表名 alter table 表名 reame 新表名: 2.新增字段名 alter table 表名 add 字段名 字段类型(数字) 约 ...
- Kotlin快速上手
一.Kotlin基础 1.数据类型声明 在Kotlin中要定义一个变量需要使用var关键字 //定义了一个可以修改的Int类型变量 var number = 39 如果要定义一个常量可以使用val关键 ...