C++进阶(十一)C++11

在这里插入图片描述


📘北尘_:个人主页

🌎个人专栏:《Linux操作系统》《经典算法试题 》《C++》 《数据结构与算法》

☀️走在路上,不忘来时的初心

文章目录

  • 一、C++11简介
  • 二、统一的列表初始化
    • 1、{}初始化
    • 2、std::initializer_list
  • 三、声明
    • 1、auto
    • 2、decltype
    • 3、 nullptr
  • 四、范围for循环
  • 五、 STL中一些变化
  • 六、 右值引用和移动语义
    • 1、左值引用和右值引用
    • 2、左值引用与右值引用比较
    • 3、右值引用使用场景和意义
    • 4、完美转发


一、C++11简介

在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于C++03(TC1)主要是对C++98标准中的漏洞进行修复,语言的核心部分则没有改动。
因此人们习惯性的把两个标准合并称为C++98/03标准。从C++0x到C++11,C++标准10年磨一剑,第二个真正意义上的标准珊珊来迟。相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。
相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大。


二、统一的列表初始化

1、{}初始化

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扩大了用大括号括起的列表(初始化列表)的使用范围,使其可用于所有的内置类型和用户定义的类型,使用初始化列表时,可添加等号(=),也可不添加。

在这里插入图片描述
创建对象时也可以使用列表初始化方式调用构造函数初始化

我们可以清楚的看到,列表初始化调用了构造函数。
在这里插入图片描述

2、std::initializer_list

std::initializer_list的介绍文档:
http://www.cplusplus.com/reference/initializer_list/initializer_list/

std::initializer_list是什么类型:

int main()
{
 // the type of il is an initializer_list 
 auto il = { 10, 20, 30 };
 cout << typeid(il).name() << endl;
 return 0;
}

在这里插入图片描述

std::initializer_list使用场景:

std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加
std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=的参数,这样就可以用大括号赋值。

int main()
{
 vector<int> v = { 1,2,3,4 };
 list<int> lt = { 1,2 };
 // 这里{"sort", "排序"}会先初始化构造一个pair对象
 map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
// 使用大括号对容器赋值
v = {10, 20, 30};
 return 0;
 }

三、声明

c++11提供了多种简化声明的方式,尤其是在使用模板时。

1、auto

在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。C++11中弃auto原来的用法,将其用于实现自动类型腿断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。

在这里插入图片描述

2、decltype

关键字decltype将变量的类型声明为表达式指定的类型。
在这里插入图片描述

3、 nullptr

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

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

在这里插入图片描述


四、范围for循环

注意:范围for的底层是迭代器
这个我们在前面的课程中已经进行了非常详细的讲解,这里就不进行讲解了,请参考C++入门+STL容器部分的课件讲解。


五、 STL中一些变化

新容器
用橘色圈起来是C++11中的一些几个新容器,但是实际最有用的是unordered_map和
unordered_set。这两个我们前面已经进行了非常详细的讲解,其他的大家了解一下即可。
在这里插入图片描述
容器中的一些新方法
如果我们再细细去看会发现基本每个容器中都增加了一些C++11的方法,但是其实很多都是用得比较少的。
比如提供了cbegin和cend方法返回const迭代器等等,但是实际意义不大,因为begin和end也是可以返回const迭代器的,这些都是属于锦上添花的操作。
实际上C++11更新后,容器中增加的新方法最后用的插入接口函数的右值引用版本。


六、 右值引用和移动语义

1、左值引用和右值引用

传统的C++语法中就有引用的语法,而C++11中新增了的右值引用语法特性,所以从现在开始我们之前学习的引用就叫做左值引用。无论左值引用还是右值引用,都是给对象取别名。

什么是左值?什么是左值引用?

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

int main()
{
	// 以下的p、b、c、*p都是左值
	int* p = new int(0);
	int b = 1;
	const int c = 2;

	// 以下几个是对上面左值的左值引用
	int*& p1 = p;
	int& p2 = *p;
	int& d = b;
	const int& m = c;
	return 0;
}

什么是右值?什么是右值引用?

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

int main()
{
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;
return 0;
}

需要注意的是右值是不能取地址的,但是给右值取别名后,会导致右值被存储到特定位置,且可以取到该位置的地址,也就是说例如:不能取字面量10的地址,但是rr1引用后,可以对rr1取地址,也可以修改rr1。如果不想rr1被修改,可以用const int&& rr1 去引用,是不是感觉很神奇,这个了解一下实际中右值引用的使用场景并不在于此,这个特性也不重要。

2、左值引用与右值引用比较

左值引用总结:

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

在这里插入图片描述
右值引用总结:

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

在这里插入图片描述

3、右值引用使用场景和意义

前面我们可以看到左值引用既可以引用左值和又可以引用右值,那为什么C++11还要提出右值引用呢?是不是化蛇添足呢?下面我们来看看左值引用的短板,右值引用是如何补齐这个短板的!

// 移动构造
 string(string&& s)
 :_str(nullptr)
 ,_size(0)
 ,_capacity(0)
 {
 cout << "string(string&& s) -- 移动语义" << endl;
 swap(s);
 }
 // 移动赋值
 string& operator=(string&& s)
 {
 cout << "string& operator=(string&& s) -- 移动语义" << endl;
 swap(s);
 return *this;
 }

左值引用的使用场景:

void func1(bit::string s)
{}
void func2(const bit::string& s)
{}
int main()
{
 bit::string s1("hello world");
 // func1和func2的调用我们可以看到左值引用做参数减少了拷贝,提高效率的使用场景和价值
 func1(s1);
 func2(s1);
 // string operator+=(char ch) 传值返回存在深拷贝
 // string& operator+=(char ch) 传左值引用没有拷贝提高了效率
 s1 += '!';
 return 0;
}

左值引用的短板:
但是当函数返回对象是一个局部变量,出了函数作用域就不存在了,就不能使用左值引用返回,只能传值返回。例如:bit::string to_string(int value)函数中可以看到,这里只能使用传值返回,传值返回会导致至少1次拷贝构造(如果是一些旧一点的编译器可能是两次拷贝构造)。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
右值引用和移动语义解决上述问题:
在bit::string中增加移动构造,移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己。
在这里插入图片描述
不仅仅有移动构造,还有移动赋值:
在bit::string类中增加移动赋值函数,再去调用bit::to_string(1234),不过这次是将
bit::to_string(1234)返回的右值对象赋值给ret1对象,这时调用的是移动构造。

// 移动赋值
string& operator=(string&& s)
{
cout << "string& operator=(string&& s) -- 移动语义" << endl;
swap(s);
return *this;
}
int main()
{
 bit::string ret1;
 ret1 = bit::to_string(1234);
 return 0;
}
// 运行结果:
// string(string&& s) -- 移动语义
// string& operator=(string&& s) -- 移动语义

这里运行后,我们看到调用了一次移动构造和一次移动赋值。因为如果是用一个已经存在的对象接收,编译器就没办法优化了。bit::to_string函数中会先用str生成构造生成一个临时对象,但是我们可以看到,编译器很聪明的在这里把str识别成了右值(将亡值),调用了移动构造。然后在把这个临时对象做为bit::to_string函数调用的返回值赋值给ret1,这里调用的移动赋值。

4、完美转发

模板中的&& 万能引用
在这里插入图片描述
模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。
但是为什么,上述的调用情况不对呢。
这里是因为,右值的右值引用将属性成了左值,否则移动赋值和移动构造将出现问题,无法交换。
我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发。
在这里插入图片描述


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

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

相关文章

微信支付服务商,商户快速进件,减少工作量

大家好&#xff0c;我是小悟 服务商拓展特约商户&#xff0c;人工录入大量商户资料&#xff0c;耗时耗力。商户对标准费率不满意&#xff0c;无法说服商户先签约再帮其调整费率。 为了减少服务商工作量&#xff0c;服务商快速进件工具来了&#xff0c;分为移动端和管理端。用好…

【Leetcode】292. Nim 游戏

文章目录 题目思路代码结果 题目 题目链接 你和你的朋友&#xff0c;两个人一起玩 Nim 游戏&#xff1a; 桌子上有一堆石头。你们轮流进行自己的回合&#xff0c; 你作为先手 。每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。拿掉最后一块石头的人就是获胜者。 假设你们每…

maven 继承

文章目录 前言一、dependencyManagement一、dependencies传递规则二、引用顺序统一声明三、maven插件默认行为声明四、动态server.name 前言 系统整理一下用到的maven继承关系 一、dependencyManagement 版本控制 <properties><!--jar版本定义 --><spring-bo…

网络编程-序列化和反序列化/应用层协议/

预备知识 理解为什么要应用层协议&#xff1f; 在学过套接字编程后&#xff0c;我们对协议的理解更深了一步&#xff0c;协议也就是一种约定&#xff0c;也可以通俗理解为一种口头约定&#xff0c;对于通信双方来说是必须要遵守的。TCP和UDP协议它们是传输层控制协议&#xf…

聚焦网络安全公司,看F5如何应对企业数字化挑战

应用无处不在的当下&#xff0c;从传统应用到现代应用再到边缘、多云、多中心的安全防护&#xff0c;安全已成为企业数字化转型中的首要挑战。有专家指出&#xff0c;目前网络安全市场已经是仅次于计算、存储、网络的第四大IT基础设施市场。那什么网络安全公司应该具有哪些能力…

Magnet AXIOM取证神器的安装使用方法及详细教程

Magnet AXIOM取证神器的安装使用方法及详细教程 公众号&#xff1a;鱼影安全1.Magnet AXIOM取证工具介绍&#xff1a;2.Magnet AXIOM取证工具安装&#xff1a;第一步&#xff1a;第二步&#xff1a; 3.Magnet AXIOM取证工具使用方法&#xff1a; 公众号&#xff1a;鱼影安全 关…

用8086汇编语言写新春祝福

本篇目录 一、前言 1.创作背景 2.最终效果 3.必要的准备 二、实现步骤 1.程序框架 2.使程序暂停一段时间的子程序 3.显示一朵烟花的子程序 &#xff08;1&#xff09;参数 &#xff08;2&#xff09;地址转换 &#xff08;3&#xff09;显示花柄 &#xff08;4&#xff09;清除…

日本承认Omotenashi任务失败

日本在征服月球的尝试失败后承认失败 25.11.2022 日本已经取消了成为第四个登上月球的国家的申请。作为阿尔忒弥斯一号任务的一部分&#xff0c;日本宇宙航空研究开发机构&#xff08;JAXA&#xff09;将其Omotenashi CubeSat与NASA的SLS火箭和猎户座飞船一起送上了月球。但在…

人生,总要读几本好书!

以前&#xff0c;没有重视过读书的重要性 但是自从进入老马的陪伴群之后&#xff0c;听了老马的一路成长经历&#xff0c;才发现&#xff0c;所谓的一鸣惊人&#xff0c;都是厚积薄发的表现 大佬们在出人头地之前&#xff0c;都是有过很长一段时间的自我提升的 这个提升的方…

【数据库】创建索引的注意事项

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;数据库 ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 结语 我的其他博客 前言 在数据库设计和优化中&#xff0c;索引的合理使用是提高查询性能和加速数据检索的关键因素之一。通过选…

浅析现代计算机启动流程

文章目录 前言启动流程概述磁盘分区格式MBR磁盘GPT磁盘隐藏分区 传统BIOS引导传统BIOS启动流程 UEFI引导UEFI引导程序UEFI启动流程 引导加载程序启动操作系统相关参考 前言 现代计算机的启动是一个漫长的流程&#xff0c;这个流程中会涉及到各种硬件的配置与交互&#xff0c;包…

《C程序设计》上机实验报告(六)之函数及其应用

实验内容&#xff1a; 1.运行程序 #include <stdio.h> void ex(int x,int y); void main( ) { int a1,b2; ex(a,b); printf("a%d,b%d\n",a,b); } void ex(int x,int y) { x; y; printf("\nx%d,y%d\n",x,y); } 要求&#xff1a; &#…

202418读书笔记|《成功的聪明人太多了,我必须为笨蛋争一口气》——做精致有趣的你呀

202418读书笔记|《成功的聪明人太多了&#xff0c;我必须为笨蛋争一口气》——做精致有趣的你呀 《成功的聪明人太多了&#xff0c;我必须为笨蛋争口气》书单狗一如既往的搞笑&#xff0c;幽默&#xff0c;博学。狗生哲学&#xff1a;做精致有趣的你呀。 趁着付费会员卡的劲儿&…

数据结构——框架简介

1.数据结构的作用 数据结构是计算机科学中一种重要的概念&#xff0c;它主要用于组织和存储数据以便有效地进行操作。数据结构可以看作是数据的组织方式&#xff0c;通过合理的数据结构设计&#xff0c;可以更高效地执行各种操作&#xff0c;提高程序的性能和可维护性。 以下是…

PyTorch 2.2 中文官方教程(十九)

使用 RPC 进行分布式管道并行 原文&#xff1a;pytorch.org/tutorials/intermediate/dist_pipeline_parallel_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 作者&#xff1a;Shen Li 注意 在github中查看并编辑本教程。 先决条件&#xff1a; PyTorc…

【Jenkins】pipeline基本使用

目录 一、pipeline 二、创建pipeline项目 1、安装pipeline插件 2、创建pipeline项目 三、pipeline语法 1、pipeline组成 2、agent&#xff1a;指定流水线的执行位置&#xff0c;流水线中每个阶段都必须在某个地方执行 3、stage&#xff1a;阶段&#xff0c;代表流水线的…

2024 高级前端面试题之 框架通识 「精选篇」

该内容主要整理关于 框架通识 的相关面试题&#xff0c;其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 框架通识精选篇 1. MVVM2. 路由原理3. Virtual Dom3.1 为什么需要 Virtual Dom3.2 Virtual Dom 算法简述3.2 Virtual Dom 算法实现 4. Diff算法4.1 React-Di…

【MySQL】学习如何使用DCL进行用户管理

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-JwFD16F1Kh0fle0X {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

五、医学影像云平台 - 医共体

原创不易&#xff0c;多谢关注&#xff01;谢谢&#xff01; 1. 医学大影像设备市场现状 目前影像设备&#xff0c;可以说低端产品同质化越来越严重&#xff0c;利润越来越薄&#xff0c;而高端超高端设备&#xff0c;整体销售额却在增长&#xff0c;利润空间也比低端的要高的…

行业应用科普 | 患者护理应用连接器

【摘要/前言】 通过医疗专业人士为患者提供护理的种种需求&#xff0c;已经不限于手术室与医院的各种安全状况。当今许多患者的护理都是在其他环境进行&#xff0c;例如医生办公室、健康中心&#xff0c;还有越来越普遍的住家。尤其是需要长期看护的患者&#xff0c;所需的科技…