【C++】C++11(统一列表初始化、声明、右值引用)

  🌈个人主页:秦jh_-CSDN博客
🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12575764.html?spm=1001.2014.3001.5482

 9efbcbc3d25747719da38c01b3fa9b4f.gif​ 

目录

C++11简介

统一的列表初始化 

{}初始化 

std::initializer_list

声明 

auto 

decltype

nullptr

STL中一些变化 

右值引用和移动语义 

左值引用和右值引用  

 左值引用与右值引用比较

 右值引用使用场景和意义

 右值引用的属性​编辑

 右值引用引用左值及其一些更深入的使用场景分析

STL容器插入接口函数也增加了右值引用版本: 

 完美转发

模板中的&& 万能引用 

 std::forward 完美转发


前言

    💬 hello! 各位铁子们大家好哇。

             今日更新了C++11的相关内容
    🎉 欢迎大家关注🔍点赞👍收藏⭐️留言📝

C++11简介

相比于 C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中 约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言, C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更 强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。

统一的列表初始化 

{}初始化 

在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。比如:

struct Point
{
 int _x;
 int _y;
};

int main()
{
 int array1[] = { 1, 2, 3, 4, 5 };
 int array2[5] = { 0 };
 Point p = { 1, 2 };
 return 0;
}

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

 

 当没有写构造函数时,无法用{}初始化自定义类型。写出构造函数后就可以,这是C++11的语法特性。本质上是通过{}构造一个A对象,然后通过拷贝构造给aa1。但是编译器会优化,连续的构造和拷贝构造会被优化为直接构造。

实际上C++98就支持了单参数的构造函数的隐式类型转换,C++11支持了多参数的。 

如果不想让隐式类型转换发生,可以在构造函数前加上explicit。 

 

单参数构造时,也可使用{},并且{}可要可不要。 甚至连内置类型也可用列表初始化。

std::initializer_list

如果使用{}初始化,像vector这种容器,我们无法知道每次初始化的参数个数是几个, 所以C++11对STL中的不少容器就增加 std::initializer_list作为参数的构造函数。

initializer_list也支持迭代器遍历。

v5是构造,v3是由 initializer_list隐式类型转换成一个vector,然后再拷贝给v3得到的。

声明 

auto 

C++11中废弃auto原来的用法,将 其用于实现自动类型腿断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初 始化值的类型。 

由上图可知,x不是i的引用。j和i的地址相同,但y和i的地址不同。如果想要y的地址与i相同,就得用auto&

decltype

typeid 可以拿到这个类型的字符串。

如果我们想用推出来的类型定义对象,不能用typeid。得用decltype。 

nullptr

由于C++中NULL被定义成字面量0,这样就可能回带来一些问题,因为0既能指针常量,又能表示 整形常量。所以出于清晰和安全的角度考虑,C++11中新增了nullptr,用于表示空指针。

STL中一些变化 

红色框中是C++11新增的容器,实际有用的是unordered_set和unordered_map。array就是静态的数组,只不过检查数组越界更严格,实际没什么用。forward_list就是一个单向链表,实际也没什么用。

右值引用和移动语义 

左值引用和右值引用  

无论左值引用还是右值引用,都是给对象取别名。 

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

 

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

 左值引用与右值引用比较

 左值引用总结:

  1. 左值引用只能引用左值,不能引用右值。
  2. 但是const左值引用既可引用左值,也可引用右值。

右值引用总结: 

  1. 右值引用只能右值,不能引用左值。
  2. 但是右值引用可以引用move以后的左值。 

 右值引用使用场景和意义

下面的测试用VS2019,VS2022优化更大,测试结果会不同。

func1中左值引用可以减少拷贝。func2中,返回值是左值引用时也可以,但如果返回值是func2中的局部对象时,出了作用域就销毁了,所以无法用左值引用返回。 

 

比如上方的to_string,str是局部对象,出了作用域就销毁了,就不能用左值引用返回。右值引用返回也是同理。

局部对象出作用域就会销毁,所以会拷贝构造一个临时对象,然后再拷贝构造给ret1。不过vs2022编译器会优化,连续的构造、拷贝构造会优化为直接构造。 

如果把上面那句话拆成两句,编译器就无法优化。先构造ret1,然后构造str,接着拷贝构造临时对象,最后进行赋值拷贝。 

 右值还可以分为纯右值(内置类型)和将亡值(自定义类型)。

STL中增加了移动构造解决上述问题:

移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己。 

// 拷贝构造
// 左值
string(const string& s)
	:_str(nullptr)
{
	cout << "string(const string& s) -- 深拷贝" << endl;

	_str = new char[s._capacity + 1];
	strcpy(_str, s._str);
	_size = s._size;
	_capacity = s._capacity;
}
	
// 移动构造
// 右值(将亡值)
string(string&& s)
	:_str(nullptr)
{
	cout << "string(string&& s) -- 移动构造" << endl;
	swap(s);
}

没有移动构造时,传左值和右值都会调用拷贝构造。有了移动构造,如果传的是右值,会优先调用移动构造。

 有了移动构造后

str是左值,要拷贝构造一个临时对象,有了移动构造,就调用移动构造给ret1。但是编译器还会继续优化,编译器将str强制识别为右值,使其调用移动构造,两次连续的移动构造又会被继续优化为一次移动构造。 

因为s3不是已存在的对象,所以编译器会优化。所以把s1强转成右值时,就会调用移动构造,交换s3和s1的资源。 

 不仅仅有移动构造,还有移动赋值:

//移动赋值
//s3 = 将亡值
string& operator=(string&& s)
{
	cout << "string(string&& s) -- 移动赋值" << endl;
	swap(s);

	return *this;
}

因为如果是用一个已经存在的对象接收,编译器就没办法优化了。 所以调用了移动构造和移动赋值。

 右值引用的属性

右值引用的属性是左值。如上图,右值引用s被当作swap函数的左值引用的形参。 

 右值引用引用左值及其一些更深入的使用场景分析

当需要用右值引用引用一个左值时,可以通过move 函数将左值转化为右值。C++11中,std::move()函数位于 头文件中,该函数名字具有迷惑性, 它并不搬移任何东西,唯一的功能就是将一个左值强制转化为右值引用。

这里我们把s1 move处理以后, 会被当成右值,调用移动构造 

STL容器插入接口函数也增加了右值引用版本: 

 

 push_back里面要new一个节点,所以会有拷贝构造。因为s1是左值,所以会调用拷贝构造。第二个push_back里是右值,就可以调用移动构造。

int类型,日期类等浅拷贝类型,没有移动系列函数。因为他们不需要拷贝构造和移动构造。浅拷贝的类不存在转移资源的说法。 

 完美转发

模板中的&& 万能引用 

 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。因为右值引用的属性是左值,所以上面Fun(t)里的t都是左值,因此会产生这个结果。如果希望能够在传递过程中保持它的左值或者右值的属性,需要用到完美转发。

 std::forward 完美转发

 完美转发保持了t的原生属性类型,即如果传的是左值,就不变。传的是右值,就推成右值引用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

对比九种MySQL高可用方案

文章目录 一、读写分离如何在业务中落地什么时候需要读写分离MySQL 主从复制技术--binlog日志主从复制过程存在主从复制延时问题主从同步延迟的解决方案主从复制如何避免丢数据总结二、对比九种MySQL高可用方案组复制、半同步复制、异步复制主从复制方案选型-异步复制主从复制方…

再用RNN神经网络架构设计生成式语言模型

上一篇&#xff1a;《用谷歌经典ML方法方法来设计生成式人工智能语言模型》 序言&#xff1a;市场上所谓的开源大语言模型并不完全开源&#xff0c;通常只提供权重和少量工具&#xff0c;而架构、训练数据集、训练方法及代码等关键内容并未公开。因此&#xff0c;要真正掌握人…

httprunner实践样例

目录 1. 安装 HTTPRunner 2. 基本概念和目录结构 3. 编写一个 HTTPRunner 测试用例&#xff08;YAML 示例&#xff09; 4. 运行测试用例 5. 使用 Python 编写测试用例 6. 运行 Python 测试用例 7. 集成测试报告 8. 高级用法&#xff1a;集成环境变量、外部数据 9. 集成…

没有在 SCM 配置或者插件中的 Git 存储库配置错误

问题&#xff1a; jenkins 配置新项目后首次运行报错如下&#xff0c;同时git代码分支无法选择。 已返回默认值 没有在 SCM 配置或者插件中的 Git 存储库配置错误 选项"使用仓库"设置为:"http://xxxx.git 请检查配置 原因&#xff1a; 配置pipeline 脚本时指…

HBU深度学习实验15-循环神经网络(2)

LSTM的记忆能力实验 飞桨AI Studio星河社区-人工智能学习与实训社区 (baidu.com) 长短期记忆网络&#xff08;Long Short-Term Memory Network&#xff0c;LSTM&#xff09;是一种可以有效缓解长程依赖问题的循环神经网络&#xff0e;LSTM 的特点是引入了一个新的内部状态&am…

算法日记 46 day 图论(并查集)

题目&#xff1a;冗余连接 108. 冗余连接 (kamacoder.com) 题目描述 有一个图&#xff0c;它是一棵树&#xff0c;他是拥有 n 个节点&#xff08;节点编号1到n&#xff09;和 n - 1 条边的连通无环无向图&#xff08;其实就是一个线形图&#xff09;&#xff0c;如图&#xff…

二叉树优选算法(一)

一、根据二叉树创建字符串 题目介绍&#xff1a; 给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 "()" 表示&#xff0c;转化后需…

RabbitMq死信队列延迟交换机

架构图 配置 package com.example.demo.config;import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;Configuration public class DeadLetterConfig {public String …

JavaWeb学习--cookie和session,实现登录的记住我和验证码功能

目录 &#xff08;一&#xff09;Cookie概述 1.什么叫Cookie 2.Cookie规范 3.Cookie的覆盖 4.cookie的最大存活时间 ​​​​​​&#xff08;Cookie的生命&#xff09; &#xff08;二&#xff09; Cookie的API 1.创建Cookie&#xff1a;new 构造方法 2.保存到客户端浏…

开启第二阶段---蓝桥杯

一、12.10--数据类型的范围及转化 今天是刚开始&#xff0c;一天一道题 对于这道题我想要记录的是Java中的整数默认是 int 类型&#xff0c;如果数值超出了 int 的范围&#xff0c;就会发生溢出错误。为了避免这个问题&#xff0c;可以将数字表示为 long 类型&#xff0c;方法…

黑马头条学习笔记

Day01-环境搭建 项目概述 课程大纲 业务说明 技术栈 Spring-Cloud-Gateway : 微服务之前架设的网关服务&#xff0c;实现服务注册中的API请求路由&#xff0c;以及控制流速控制和熔断处理都是常用的架构手段&#xff0c;而这些功能Gateway天然支持 运用Spring Boot快速开发…

详解RabbitMQ在Ubuntu上的安装

​​​​​​​ 目录 Ubuntu 环境安装 安装Erlang 查看Erlang版本 退出命令 ​编辑安装RabbitMQ 确认安装结果 安装RabbitMQ管理界面 启动服务 查看服务状态 通过IP:port访问 添加管理员用户 给用户添加权限 再次访问 Ubuntu 环境安装 安装Erlang RabbitMq需要…

SpringBoot【二】yaml、properties两配置文件介绍及使用

一、前言 续上一篇咱们已经搭建好了一个springboot框架雏形。但是很多初学的小伙伴私信bug菌说&#xff0c;在开发项目中&#xff0c;为啥.yaml的配置文件也能配置&#xff0c;SpringBoot 是提供了两种2 种全局的配置文件嘛&#xff0c;这两种配置有何区别&#xff0c;能否给大…

Excel的文件导入遇到大文件时

Excel的文件导入向导如何把已导入数据排除 入起始行&#xff0c;选择从哪一行开始导入。 比如&#xff0c;前两行已经导入了&#xff0c;第二次导入的时候排除前两行&#xff0c;从第三行开始&#xff0c;就将导入起始行设置为3即可&#xff0c;且不勾选含标题行。 但遇到大文…

Windows平台Unity3D下RTMP播放器低延迟设计探讨

技术背景 好多开发者希望我们分享下大牛直播SDK是如何在Unity下实现低延迟的RTMP播放的&#xff0c;以下是一些降低 Unity 中 RTMP 播放器延迟的方法&#xff1a; 一、选择合适的播放插件或工具 评估和选用专业的流媒体插件 市场上有一些专门为 Unity 设计的流媒体插件&…

PaddleOCR模型ch_PP-OCRv3文本检测模型研究(一)骨干网络

从源码上看&#xff0c;PaddleOCR一共支持四个版本&#xff0c;分别是PP-OCR、PP-OCRv2、PP-OCRv3、PP-OCRv4。本文选择PaddleOCR的v3版本的骨干网络作为研究对象&#xff0c;力图探究网络模型的内部结构。 文章目录 研究起点卷归层压发层残差层骨干网代码实验小结 研究起点 参…

log4j漏洞复现--vulhub

声明&#xff1a;学习过程参考了同站的B1g0rang大佬的文章 Web网络安全-----Log4j高危漏洞原理及修复(B1g0rang) CVE-2021-44228 RCE漏洞 Log4j 即 log for java(java的日志) &#xff0c;是Apache的一个开源项目&#xff0c;通过使用Log4j&#xff0c;我们可以控制日志信息输…

计算机网络ENSP课设--三层架构企业网络

本课程设计搭建一个小型互联网&#xff0c;并模拟Internet的典型Web服务过程。通过此次课程设计&#xff0c;可以进一步理解Internet的工作原理和协议过程&#xff0c;并提高综合知识的运用能力和分析能力。具体目标包括&#xff1a; &#xff08;1&#xff09;掌握网络拓扑的…

SQL 获取今天的当月开始结束范围:

使用 GETDATE() 结合 DATEADD() 和 DATEDIFF() 函数来获取当前月的开始和结束时间范围。以下是实现当前月时间范围查询的 SQL&#xff1a; FDATE > DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0) FDATE < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()) 1, 0) …

Go的Gin比java的Springboot更加的开箱即用?

前言 隔壁组的云计算零零后女同事&#xff0c;后文简称 云女士 &#xff0c;非说 Go 的 Gin 框架比 Springboot 更加的开箱即用&#xff0c;我心想在 Java 里面 Springboot 已经打遍天下无敌手&#xff0c;这份底蕴岂是 Gin 能比。 但是云女士突出一个执拗&#xff0c;非我要…