【C++历练之路】C++11中的列表初始化声明新方法深入标准模板库的变革

W...Y的主页 😊 

代码仓库分享💕


目录

1. C++11简介

2. 统一的列表初始化

2.1 {}初始化

2.2 std::initializer_list

3. 声明

3.1 auto

3.2 decltype

 4.STL中一些变化


1. 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能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更
强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个
重点去学习。
C++11增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以次主要讲解实际中比较实用的语法。 

C++11内容icon-default.png?t=N7T8https://en.cppreference.com/w/cpp/11

2. 统一的列表初始化

2.1 {}初始化

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

struct Point
{
    int _x;
    int _y;
};
int main()
{
    int x1 = 1;
    int x2{ 2 };
    int array1[]{ 1, 2, 3, 4, 5 };
    int array2[5]{ 0 };
    Point p{ 1, 2 };
    // C++11中列表初始化也可以适用于new表达式中
    int* pa = new int[4]{ 0 };
    return 0;
}

创建对象时也可以使用列表初始化方式调用构造函数初始化

class Date
{
public:
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{
cout << "Date(int year, int month, int day)" << endl;
}
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 };
return 0;
}

2.2 std::initializer_list

std::initializer_list的介绍文档:

initializerLlist文档icon-default.png?t=N7T8http://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;
}

 initializer_list是C++11新增内容,其是一个模板对应的auto会识别大括号中的数据类型,做出相应的转变。

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新增的 initializer_list,STL容器中提供这样的initializer_list的构造接口。而我们使用的{}进行结构体的初始化是多参数的隐式类型转换。

list文档     vector文档    map文档    这些STL容器中都支持initializer_list构造。

3. 声明

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

3.1 auto

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

int main()
{
int i = 10;
auto p = &i;
auto pf = strcpy;
cout << typeid(p).name() << endl;
cout << typeid(pf).name() << endl;
map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
return 0;
}

3.2 decltype

关键字decltype将变量的类型声明为表达式指定的类型。

`decltype`是C++11中引入的一个类型特征,用于确定表达式的类型。

1. 类型推断:`decltype`用于自动推断表达式的类型,而不需要显式地指定类型。

2. 模板编程:在模板元编程中,`decltype`常用于根据模板参数的类型来推导返回类型。

3. 函数签名:`decltype`可以用来声明函数,其中函数的返回类型由函数体中的返回语句确定。

4. lambda表达式:在使用lambda表达式时,`decltype`可以用来推断lambda的捕获类型。

5. 智能指针:在使用智能指针(如`std::unique_ptr`、`std::shared_ptr`)时,`decltype`可以用来获取智能指针所指向的类型。

6. 类型安全:`decltype`提供了一种类型安全的方式来处理类型,确保代码中使用的类型与预期一致。

7. 避免类型转换:`decltype`可以避免不必要的类型转换,因为它直接使用表达式的静态类型。

8. 与auto结合使用:`decltype`经常与`auto`关键字结合使用,`auto`用于变量声明,而`decltype`用于类型推断。

9. 类型特征:`decltype`可以与类型特征(如`std::is_same`)结合使用,进行编译时的类型检查。

10. 避免类型别名:在某些情况下,`decltype`可以用来避免创建冗余的类型别名。

`decltype`的引入提高了C++代码的灵活性和表达能力,特别是在模板编程和类型推断方面。

template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}
int main()
{
const int x = 1;
double y = 2.2;
decltype(x * y) ret; // ret的类型是double
decltype(&x) p;    // p的类型是int*
cout << typeid(ret).name() << endl;
cout << typeid(p).name() << endl;
F(1, 'a');
return 0;
}

C++中的autodecltype都是用于类型推断的关键字,但它们的用途和行为有所不同:

  1. auto关键字

    • auto用于声明变量时自动推断其类型。
    • 它基于变量的初始化表达式来确定类型。
    • 在模板元编程中,auto通常用于从模板参数中推断类型。
    • 当使用auto声明变量时,如果初始化表达式是一个复杂类型,auto会推断出该复杂类型。
  2. decltype关键字

    • decltype用于获取一个表达式的类型,而不管表达式是否有值。
    • 它不会对表达式求值,只关注表达式的类型。
    • decltype常用于获取函数返回类型或对象类型,特别是当这些类型依赖于模板参数时。
    • 如果decltype用于未命名的右值,它会推断出对应的引用类型,例如decltype(表达式)会推断出表达式的引用类型。
  3. 类型推断差异

    • auto在声明时会进行类型推断,如果初始化表达式是一个类型别名或decltype表达式,auto将推断出实际的类型。
    • decltype总是推断出表达式的确切类型,包括引用和const限定符。
  4. 使用场景

    • auto通常用于简化模板代码的编写,尤其是在类型很长或复杂时。
    • decltype常用于需要精确知道表达式类型的情况,例如在编写需要返回与函数签名相同类型的模板代码时。
  5. 类型别名

    • auto可以用于声明类型别名,但实际类型会在声明时被推断出来。
    • decltype不会创建类型别名,它只是提供了一种获取现有类型的方式。
  6. 函数返回类型

    • 使用auto声明函数时,函数的返回类型将由函数体中的返回语句来确定。
    • 使用decltype声明函数时,返回类型将直接是函数签名中指定的类型。

总结来说,autodecltype都用于类型推断,但auto更侧重于简化代码和自动推断类型,而decltype则提供了一种获取表达式确切类型的机制。

 4.STL中一些变化

新容器

用橘色圈起来是C++11中的一些几个新容器,但是实际最有用的是unordered_map和
unordered_set。这两个我们前面已经进行了非常详细的讲解,其他的大家了解一下即可。

 

容器中的一些新方法
如果我们再细细去看会发现基本每个容器中都增加了一些C++11的方法,但是其实很多都是用得
比较少的。
比如提供了cbegin和cend方法返回const迭代器等等,但是实际意义不大,因为begin和end也是
可以返回const迭代器的,这些都是属于锦上添花的操作。
实际上C++11更新后,容器中增加的新方法最后用的插入接口函数的右值引用版本

但是这些接口到底意义在哪?网上都说他们能提高效率,他们是如何提高效率的? 欲知后事如何请看下一篇博客解说。


以上就是本次全部内容,感谢大家观看。

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

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

相关文章

响应式流规范解析

在互联网应用构建过程中&#xff0c;我们知道可以采用异步非阻塞的编程模型来提高服务的响应能力。而为了实现异步非阻塞&#xff0c;我们可以引入数据流&#xff0c;并对数据的流量进行控制。我们来考虑一个场景&#xff0c;如果数据消费的速度跟不上数据发出的速度&#xff0…

腺苷调节合成高密度脂蛋白用于三阴性乳腺癌的化学免疫治疗

引用信息 文 章&#xff1a;Adenosine-modulating synthetic high-density lipoprotein for chemoimmunotherapy of triple-negative breast cancer 期 刊&#xff1a;Journal of Controlled Release&#xff08;影响因子&#xff1a;10.8&#xff09; 发表时间&am…

webgl_effects_stereo

ThreeJS 官方案例学习&#xff08;webgl_effects_stereo&#xff09; 1.效果图 2.源码 <template><div><div id"container"></div></div> </template> <script> import * as THREE from three; // 导入控制器 import { …

【乐吾乐2D可视化组态编辑器】实时数据,数据绑定

什么是绑定变量&#xff1f; 绑定变量是指把图元的一个属性与设备数据点关联的一个过程。【注意】只是建立一个数据模型的关联&#xff0c;数据源后面设置。 乐吾乐2D可视化组态编辑器地址&#xff1a;https://2d.le5le.com/ 为什么不直接设置数据源&#xff1f; 方便批量…

AWS-生产级微服务部署架构分享

使用AWS搭建云上应用 名词解释 AWS ECR&#xff1a;AWS ECR 容器存储库&#xff0c;按项目名创建容器仓库&#xff0c;一个项目对应一个仓库&#xff0c;目前是由Jenkins构建镜像远程push到AWS ECR。 **AWS ECS&#xff1a;Amazon Elastic Container Service (ECS) &#xf…

物理安全防护如何创新强化信息安全体系?

物理安全防护是信息安全体系的重要组成部分&#xff0c;它通过保护实体设施、设备和介质等&#xff0c;防止未授权访问、破坏、盗窃等行为&#xff0c;从而为信息系统提供基础的安全保障。要创新强化信息安全体系中的物理安全防护&#xff0c;可以从以下几个方面着手&#xff1…

AI查重与降重:科研人员的新型助手

论文写作低效&#xff1f;试试这四款AI论文工具和降重技术&#xff01;-笔灵 副本 在科研领域&#xff0c;AI写作工具如同新一代的科研利器&#xff0c;它们能够极大提高文献查阅、思路整理和表达优化的效率&#xff0c;本质上促进了科研工作的进步。AI写作工具不仅快速获取并…

k8s AIOps

k8s AIOps 主要介绍下k8sgpt 官站 github 介绍 k8sgpt 是一个用于扫描Kubernetes集群、诊断和分级问题的工具。它以简单的英语呈现问题&#xff0c;并将站点可靠性工程&#xff08;SRE&#xff09;的经验编码到其分析器中。通过AI丰富问题的解释&#xff0c;k8sgpt帮助提取最…

面试题react03

React事件机制&#xff1a; React的事件机制可以分为两个部分&#xff1a;事件的触发和事件的处理。事件的触发&#xff1a;在React中&#xff0c;事件可以通过用户与组件进行交互而触发&#xff0c;如点击、鼠标移动、键盘输入等。当用户与组件进行交互时&#xff0c;浏览器会…

mysql 8 linux7,8安装教程

选择自己对应的linux版本 cat /etc/os-release //查看自己linux系统版本 1.mysql下载地址 MySQL :: Download MySQL Community Server (Archived Versions) 拉到下面找到 选择自己linux指定的版本&#xff0c;否则会很麻烦 cat /etc/os-release //查看系统版本 2.查…

为什么给网站安装SSL证书之后还是有被提示不安全?

分为两种情况一种是安装了付费证书之后还是显示无效&#xff0c;另一种是安装了免费SSL证书的。 付费SSL证书&#xff1a;直接找厂商帮助解决遇到的问题&#xff0c;一般都是有专业的客服来对接这些的。 免费SSL证书&#xff1a;出现这种情况的原因会有很多。因为免费SSL证书的…

代码随想录-二叉树 | 101对称二叉树

代码随想录-二叉树 | 101对称二叉树 LeetCode 101-对称二叉树解题思路代码难点总结 LeetCode 101-对称二叉树 题目链接 代码随想录 题目描述 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 解题思路 判断&#xff1a; 同时遍历并比较根节点的左、右子树。…

服务器数据恢复—强制上线raid5阵列离线硬盘导致raid不可用的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌2850服务器中有一组由6块SCSI硬盘组建的raid5磁盘阵列&#xff0c;linux操作系统ext3文件系统。 服务器故障&#xff1a; 服务器运行过程中突然瘫痪。服务器管理员检查阵列后发现raid5阵列中有两块硬盘离线&#xff0c;将其中一块硬盘进行…

3、前端本地环境搭建

前端本地环境搭建 安装node [node下载地址] https://nodejs.org/en/download/prebuilt-installer 选择LTS的版本进行下载 下载后直接双击点击&#xff0c;选择自己想要安装到的目录一直点下一步即可&#xff08;建议不要安装到c盘&#xff09; 安装完成后配置环境变量&am…

JSON 无法序列化

JSON 无法序列化通常出现在尝试将某些类型的数据转换为 JSON 字符串时&#xff0c;这些数据类型可能包含不可序列化的内容。 JSON 序列化器通常无法处理特定类型的数据&#xff0c;例如日期时间对象、自定义类实例等。在将数据转换为 JSON 字符串之前&#xff0c;确保所有数据都…

PHP线上文具商城设计与实现-计算机毕业设计源码65198

摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针对线上文具商城 等问题&#xff0c;对线上文具…

Python 和 Java 实现云计算的最终年项目

1、问题背景 目前&#xff0c;我正在进行我的最终年项目&#xff0c;计划用 Python 编写一个云计算系统&#xff0c;而云客户端将由我的团队成员使用 Java 来编写。这个云客户端将具有一个带有标签的界面&#xff0c;并提供文本编辑器、媒体播放器、几个基于 Java 的小游戏以及…

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048

20240607给Toybrick的TB-RK3588开发板在Buildroot下适配瑞芯微7.86寸QXGATFT-LCD EDP屏幕1536x2048 2024/6/7 13:59 1、背光部分&#xff1a;&backlight { pwms <&pwm2 0 25000 0>; status "okay"; }; &pwm2 { status "okay&…

5、搭建前端项目

5.1 使用vite vue搭建 win r 打开终端 切换到你想要搭建的盘 npm init vitelatest跟着以下步骤取名即可 cd fullStackBlognpm installnpm run dev默认在 http://localhost:5173/ 下启动了 5.2 用vscode打开项目并安装需要的插件 1、删除多余的 HelloWorld.vue 文件 2、安装…

linux驱动学习(七)之混杂设备

需要板子一起学习的可以这里购买&#xff08;含资料&#xff09;&#xff1a;点击跳转 一、混杂设备 混杂设备也叫杂项设备&#xff0c;是对普通的字符设备(struct cdev)的一种封装,设计目的就是为了简化字符设备驱动设计的流程。具有以下特点&#xff1a; 1) 主设备号为10&a…