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将要加入的最重大语言特性之一.从实践 ...
随机推荐
- Mqtt开发笔记:windows下C++ ActiveMQ客户端介绍、编译和使用
前话 项目需求,需要使用到mqtt协议,之前编译QtMqtt库,不支持队列模式queue(点对点),只支持订阅/发布者模式.,所以使用C++ ActiveMQ实现. MQTT协议 简介 M ...
- 我说MySQL联合索引遵循最左前缀匹配原则,面试官让我回去等通知
面试官: 我看你的简历上写着精通MySQL,问你个简单的问题,MySQL联合索引有什么特性? 心想,这还不简单,这不是问到我手心里了吗? 听我给你背一遍八股文! 我: MySQL联合索引遵循最左前缀匹 ...
- vue脚手架创建项目后使用路由报错Object(...) is not a function问题
在这之前我做过的vue项目没有这种问题,今天突然出现这个问题,也检查了很久的代码,最后解决我也不知道我是哪一步做错了 首先我是创建的vue2项目,基本操作跟平常一样,在运用路由跳转的时候遇到这个问题 ...
- django自带的序列化组件
1.什么是序列化组件 在django中,自带一个序列化组件,它是用来将数据进行整理.转化成特定的为一个特定的格式(比如json数据格式),然后传输给前端,以便前端对数据进行处理操作. 2.为什么要用序 ...
- vue 将markdown字符串转html、修改主题、生成目录
前言 将 markdown 字符串转成 html 显示出来,同时把目录也提取出来一起显示.可以使用 marked 来读取 markdown 字符串解析成 html marked官网:https://m ...
- Redis 11 配置
参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 基本配置 Re ...
- Java SE 15 新增特性
Java SE 15 新增特性 作者:Grey 原文地址:Java SE 15 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...
- 有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成。
有一个线性表,采用带头结点的单链表L来存储,设计一个算法将其逆置,且不能建立新节点,只能通过表中已有的节点的重新组合来完成. 分析:线性表中关于逆序的问题,就是用建立链表的头插法.而本题要求不能建立新 ...
- 【NOI P模拟赛】(要素过多的标题)(容斥原理)
题面 0 题目背景 [ 数 据 删 除 ] _{^{[数\,据\,删\,除]}} [数据删除] 1 题目描述 在执行任务时,收集到了 n n n 份能源,其中第 i i i 份的能量值是 ...
- [CF1527D] MEX Tree (lca)
题面 给你一棵 n n n 个结点的树,对于所有的 k ∈ [ 0 , n ] k\in[0,n] k∈[0,n] ,求出 M E X = k {\rm MEX}=k MEX=k 的路径数量. 一条路 ...