【C++11(一)】右值引用以及列表初始化

💓博主CSDN主页:杭电码农-NEO💓

⏩专栏分类:C++从入门到精通⏪

🚚代码仓库:NEO的学习日记🚚

🌹关注我🫵带你学习C++
  🔝🔝


在这里插入图片描述

C++11

  • 1. 前言
  • 2. 统一的列表初始化
  • 3. initializer_list容器讲解
  • 4. 左值与右值引用的初步认识
  • 5. 左值引用与右值引用比较
  • 6. 右值引用的使用场景以及价值
  • 7. 模板中的万能引用:&&
  • 8. 总结以及拓展

1. 前言

在C++98过后,更新的最重大,最有意义的就是C++11,
C++11新增了很多实用的内容,
C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,
不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,
不仅如此,面试时也会问C++11的内容,所以我们要作为一个重点去学习

关于C++11的小故事:

在这里插入图片描述

本章重点:

本篇文章着重讲解C++11中新增的
统一的列表初始化{},及其底层容器:
initializer_list.并且会着重讲解C++11
中的右值引用相关内容,关于右值引用
的内容多并且杂,请同学们耐心学习!


2. 统一的列表初始化

请注意,用列表初始化和使用初始化
列表是两个完全不一样的概念!

不知道各位在写代码有没有这样写过:

vector<int> vv{1,2,3,4,5,6};
vector<int> vv = {1,2,3,4,5,6};

这就是使用列表来初始化容器!

C++11扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

即使都是用列表初始化,但种类可能不同:

class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;};
int main()
{Date d1(2022, 1, 1); // old style// C++11支持的列表初始化,这里会调用构造函数初始化Date d2{ 2022, 1, 2 };Date d3 = { 2022, 1, 3 };vector<int> v{1,2,3};return 0;
}

上面代码中,用列表初始化Date类和
vector类是不一样的,因为使用列表初
初始化Date时列表中的参数个数和类型
必须和Date中构造函数的参数个数类型
匹配,你不能写成Date d{2022}.但是在
vector初始化时,列表中的参数个数可以
是任意多个.

列表参数个数与构造函数一样的是隐式类型转换

你甚至可以这样用列表初始化:

vector<Date> vv{ {2023,12,2}, {2023,12,3}, {2023,12,4}};
map<string,int> mm{ {"西瓜",1}, {"苹果",2}, {"香蕉",3}};

3. initializer_list容器讲解

C++11中,大括号可以被识别为
一种类型,请看下面的代码验证:

auto it = { 1,2,3,4 };//li是initializer_list类型
cout << typeid(it).name() << endl;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

到这里,我们就能理解为啥STL的容器
可以支持用列表初始化了,因为它的内
部的构造函数和operator=函数重载了
参数是initializer_list的版本,所以当外界
使用列表初始化时,内部会识别为
initializer_list类型就会去调用特定的构造!

随便看看几个容器的构造版本:
(注意要看C++11版本的)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

并且initializer_list的内容不可修改
它指向的内容在常量区


4. 左值与右值引用的初步认识

首先,要先分清左值和右值的区别
左值的概念:

左值是一个表示数据的表达式(如变量名或解引用的指针),我们可以获取它的地址+可以对它赋值,左值可以出现赋值符号的左边,右值不能出现在赋值符号左边。定义时const修饰符后的左值,不能给他赋值,但是可以取它的地址。左值引用就是给左值的引用,给左值取别名

// 以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;

右值的概念:

右值也是一个表示数据的表达式,如:字面常量、表达式返回值,函数返回值(这个不能是左值引用返回)等等,右值可以出现在赋值符号的右边,但是不能出现出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值取别名

double x = 1.1, y = 2.2;
// 以下几个都是常见的右值
10;
x + y;
fmin(x, y);
// 以下几个都是对右值的右值引用
int&& rr1 = 10;
double&& rr2 = x + y;
double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值
10 = 1;
x + y = 1;
fmin(x, y) = 1;

注意,并不能用一个值能不能修改来区分左右值
const修饰的左值也不能修改,右值引用是&&

总结:

  • 区分左值和右值最常用的方法是看它
    能不能取地址,能取地址的是左值!

  • 虽然右值不能取地址,但是可以对使用
    右值引用后的变量取地址!

int&& r = 10;
int* pr = &r;

5. 左值引用与右值引用比较

先说它们两个的结论:

  • 左值引用只能引用左值,不能引用右值
    但const左值引用能引用右值

  • 右值引用只能引用右值,不能引用左值
    但右值引用可以引用move后的左值

代码检验:

// 左值引用只能引用左值,不能引用右值。
int a = 10;
int& ra1 = a;   // ra为a的别名
//int& ra2 = 10;   // 编译失败,因为10是右值
// const左值引用既可引用左值,也可引用右值。
const int& ra3 = 10;
const int& ra4 = a;
--------------------------------------------------
// 右值引用只能右值,不能引用左值。
int&& r1 = 10;
// error C2440: “初始化”: 无法从“int”转换为“int &&”
// message : 无法将左值绑定到右值引用
int a = 10;
int&& r2 = a;
// 右值引用可以引用move以后的左值
int&& r3 = std::move(a);

move是标准库中的一个函数,它可以将
一个变量/对象变成"将亡值",比如说现在
有一个数据的存在只是为了初始化另外
一个数据,那么如果不使用move的话,编译器
会将原先的数据给目标数据拷贝一份,并且
原先的数据即使已经没用了也会等到出了
作用域再销毁,加入我们使用move,编译器就
不会将原先的数据拷贝至目标数据,而是将
原先的数据直接给目标数据,而原先的数据清0!

在这里插入图片描述


6. 右值引用的使用场景以及价值

其实右值引用的价值刚刚已经谈到过了,
特别是在一些STL容器中,我们push一个
10,10是右值,此时不用拷贝直接此资源
做交换即可,或者说push了一个以后不需
要的值,也就是将亡值,此时也可以直接交换!

正因为如此,C++11的STL容器的构造
函数和赋值函数都重载了右值版本:

在这里插入图片描述
在这里插入图片描述

右值版本的构造很简单,直接swap资源即可
不需要像左值一样做拷贝,增加了效率!

//编译器识别为右值,直接调用右值引用版本的构造
string str("abcdef");
list<string> lt;
//move后编译器识别为右值,push后原本的str就被清0了
lt.push_back(move(str));

库中重载的右值引用版本的构造和赋值
被称为"移动构造"和移动赋值",它们极大的
提高的很多场景下的效率!

并且在函数返回值问题上,右值引用也能
发挥意想不到的作用,请看下面的例子:

string to_string(int val)
{string ret;//...将整数转换为字符串return ret;
}
string s1 = to_string(123);

如果没有移动构造和移动赋值,这里
return ret后会先将ret拷贝给临时对象
然后这个临时对象再把数据赋值给
外面的s1对象,这里要经历两次拷贝
可以说效率极其低下,其过程图如下:

在这里插入图片描述
假如我们实现的移动构造,编译器会把
ret识别为将亡值,就会去调用移动构造,
并且经过编译器的优化后,这两步拷贝
构造最终会被优化为一步移动赋值!

在这里插入图片描述


7. 模板中的万能引用:&&

模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值,模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力

请看下面的代码:

void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }
void Fun(int &&x){ cout << "右值引用" << endl; }
void Fun(const int &&x){ cout << "const 右值引用" << endl; }template<class T>
void PerfectForward(T&& t)//万能引用
{Fun(t);
}
int main()
{PerfectForward(10);//右值           int a;PerfectForward(a);//左值            PerfectForward(std::move(a));//右值const int b = 8;PerfectForward(b);//左值PerfectForward(std::move(b));//右值 return 0;
}

第一层per函数的参数既能接受左值
也能接受右值,但是假如你把代码复制
后测试,会发现在参数传递到第二层函数
时,它全部变成的左值,这是因为模板中的
万能引用会将右值退化成左值,所以后续
使用过程它就变成了左值!

使用forward可以保留对象的原生类型

void PerfectForward(T&& t)
{Fun(std::forward<T>(t));
}

注意,如果有多层调用,那么每一层都要加forward


8. 总结以及拓展

C++11之后,类的六个默认成员函数
又增加了两个,移动构造和移动赋值,
对于这两个函数需要注意下面几个点:

在这里插入图片描述

文章内容已经完结,有问题欢迎私信


🔎 下期预告:lambda表达式和包装器🔍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/210301.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机远程温控检测系统

**单片机设计介绍&#xff0c;基于单片机远程温控检测系统&#xff08;含上位机&#xff09; 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的远程温控检测系统可以用于远程监测和控制温度&#xff0c;实现远程温度监…

城市NOA加速落地,景联文科技高质量数据标注助力感知系统升级

当前&#xff0c;自动驾驶技术的演进正在经历着从基础L2到L3过渡的重要阶段&#xff0c;其中NOA&#xff08;自动辅助导航驾驶&#xff09;扮演着至关重要的角色。城市NOA&#xff08;L2.9&#xff09;作为城市场景下的NOA&#xff0c;被看作是车企向更高阶自动驾驶迈进的必经之…

计算机基础知识61

JsonResponse 功能例子 你自己写一个类&#xff0c;实现JsonResponse 功能&#xff0c;不需要传safeFalse&#xff0c;无论字典或列表&#xff0c;都能完成序列化返回给前端 1 响应头例子 四种情况&#xff0c;在响应头返回数据 xxxx # 第一种情况 JsonResponse def show(req…

Python调用腾讯云短信服务发送手机短信

文章目录 1、准备工作2、代码实现3、拓展4、闲聊关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Python兼职渠道 1、准备工作 p…

身份统一管理创新与优化 ——华为云OneAccess应用身份管理服务的2023年

2023年&#xff0c;随着云计算、物联网、人工智能等技术的快速发展&#xff0c;企业面临着数字化转型的巨大挑战与机遇。身份统一管理是企业数字化转型的基础&#xff0c;也是业务发展的关键。如何高效、安全、灵活地实现身份统一管理&#xff0c;成为企业亟待解决的首要课题。…

硬盘分区丢失?这样轻松恢复!

​“在我安装操作系统的过程中&#xff0c;我先把C盘&#xff08;100G&#xff09;进行了格式化&#xff0c;而我的D盘大小为297G&#xff0c;然而在Win PE中&#xff0c;所显示的仅是247G&#xff08;CD盘总容量&#xff09;&#xff0c;这247G是空无一物的。让我感到困惑的是…

D7292 双向直流电机驱动电路 ( 速度可控 ) 7V~20V 400mA,峰值电流可达1.2A 采用DIP8、SOP8的封装形式

D7292是一块带有制动和速度控制功能的双向直流电机单片电路。它可以用来驱动CDP、VCR 和 TOY等负载。该电路通过两个逻辑输入管脚的电压&#xff0c;可以控制电机正反 个方向转动以及制动。并且可以通过改变速度控制管脚的电压&#xff0c;从而方便的改变电机的速度。D7292采用…

前端项目中CDN的一些问题【性能优化篇】

1. CDN的概念 CDN&#xff08;Content Delivery NetWork&#xff0c;内容分发网络&#xff09;&#xff0c;是指利用最靠近每位用户的服务区&#xff0c;更快的将资源发送给用户。 提高用户的访问速度减轻服务器压力提高网站的稳定性和安全性 2. CDN的作用 CDN一般用来托管…

WPF绘制进度条(弧形,圆形,异形)

前言 WPF里面圆形进度条实现还比较麻烦,主要涉及到的就是动态绘制进度条的进度需要用到简单的数学算法。其实原理比较简单,我们需要的是话两条重叠的弧线,里面的弧线要比里面的弧线要宽,这样简单的雏形就出来了。 基础写法 我们可以用Path来绘制弧线,代码如下: <Gr…

双向ESD保护 汽车级TVS二极管 ESD9B3.3ST5G工作原理、特性参数、封装形式

什么是汽车级TVS二极管&#xff1f; TVS二极管是一种用于保护电子电路的电子元件。它主要用于电路中的过电压保护&#xff0c;防止电压过高而损坏其他部件。TVS二极管通常被称为“汽车级”是因为它们能够满足汽车电子系统的特殊要求。 在汽车电子系统中&#xff0c;由于车辆启…

怎么对文件加密?文件加密软件操作保姆式演示!

大家是不是遇到过这种情况&#xff0c;文件一个不小心就被别人轻易外发出去&#xff0c;并且还是特别重要的内容。在企业中这种现象已经非常常见啦。 今天就给友友们&#xff0c;分享一款神器&#xff0c;它可以让你点点鼠标&#xff0c;就对企业的重要文件进行加密。 1、获取…

Hdoop学习笔记(HDP)-Part.17 安装Spark2

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

[HTML]Web前端开发技术6(HTML5、CSS3、JavaScript )DIV与SPAN,盒模型,Overflow——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

分享67个节日PPT,总有一款适合您

分享67个节日PPT&#xff0c;总有一款适合您 67个节日PPT下载链接&#xff1a;https://pan.baidu.com/s/1oU-UUCV_69e8Gp5Y6zrzVA?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;收集整理更不易…

Interpretable Multimodal Misinformation Detection with Logic Reasoning

原文链接 Hui Liu, Wenya Wang, and Haoliang Li. 2023. Interpretable Multimodal Misinformation Detection with Logic Reasoning. In Findings of the Association for Computational Linguistics: ACL 2023, pages 9781–9796, Toronto, Canada. Association for Computa…

uniapp自定义进度条组件

目标效果 原型设计为这样的样式&#xff0c;但是现有的进度条组件样式都无法满足需求&#xff0c;于是编写组件实现。 设计引用格式为 <zLineProgress :total"15" :val"7" title"你好吗" />定义组件 <template><view style&…

递增子序列(回溯)

题目描述 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0c;也可以视作递增序列的一种特殊情况。 样例…

继上海车展后,英信翻译再进广州车展大显身手

第二十一届广州车展于2023年11月17日-26日在广州琶洲盛大举行 &#xff0c;历时十天的展会共吸引到场观众84.7万人次&#xff0c;举办了67场新闻发布会&#xff0c;近5000家海内外媒体机构的1.2万名媒体人员参与报道了展会盛况&#xff0c;再创历史新高。本届广州车展在国内外企…

Oracle(2-9) Oracle Recovery Manager Overview and Configuration

文章目录 一、基础知识1、User Backup VS RMAN2、Restoring &Recovering DB 还原&恢复数据库3、Recovery Manager Features 管理恢复功能4、RMAN Components RMAN组件5、Repository1: Control File 存储库1:控制文件6、Channel Allocation 通道道分配7、Media Manageme…

解决IDEA springboot“spring-boot-maven-plugin“报红问题方法

本篇文章小编给大家分享一下解决IDEA springboot"spring-boot-maven-plugin"报红问题方法&#xff0c;文章代码介绍的很详细&#xff0c;小编觉得挺不错的&#xff0c;现在分享给大家供大家参考&#xff0c;有需要的小伙伴们可以来看看。 使用环境 项目环境&#x…