C++11——基础新增特性

目录

  • C++11介绍
  • 统一的列表初始化
    • 对内置类型
    • initializer_list
  • 声明
    • auto
    • decltype
    • nullptr
  • 范围for
  • 容器新增接口
    • emplace
    • 容器的新方法

C++的前身是“C with Classes”, 最早于 1979年由 祖师爷Bjarne Stroustrup(本贾尼·斯特劳斯特鲁普) 在贝尔实验室开始设计,旨在将 Simula(一种具有重大历史意义的编程语言)的 面向对象特性引入C语言。于1983年正式命名为C++。

作为如今热门的主流编程语言,C++有其制定标准与特性的委员会。
标准委员会成立:1990年,C++标准委员会成立,开始C++的标准化进程。
C++98标准: 1998年,发布了第一个C++正式标准,即C++98。这个标准使得C++更加稳定,并被广泛采用。同时,C++的标准库也得到了扩展,引入了诸如STL(Standard Template Library) 等功能。

历史发展
1998年是C++标准委员会成立的第一年,本来计划以后每5年视实际需要更新一次标准,C++国际标准委员会在研究C++ 03的下一个版本的时候,一开始计划是2007年发布,所以最初这个标准叫C++ 07。但是到06年的时候,官方觉得2007年肯定完不成C++ 07,而且官方觉得2008年可能也完不成。最后干脆叫C++ 0x。x的意思是不知道到底能在07还是08还是09年完成。结果2010年的时候也没完成,最后在2011年终于完成了C++标准。所以最终定名为C++11。这也是为什么经常听到C++98,C++11的原因,期间的多个版本要么是难产,要么只是对之前大版本的打补丁。直到C++11的到来。

C++11历经九九八十一难,终于艰难问世…,要知道隔壁 Java 可是每两年乃至每六个月更新一次新标准。于是,在C++11之后,委员会规定每三年更新一次新标准。

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++11主要更新:
相比于C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言,C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多,所以我们要作为一个重点去学习。C++11增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以本文主要讲解实际中比较实用的语法。

C++11新增特性
C++11 官网:https://en.cppreference.com/w/cpp/11

后续标准与修订:

  • C++03标准:2003年,发布了C++03标准,对C++98仅有很少的修订。
  • C++11标准:2011年,发布了C++11标准,这是C++标准的一次重大升级,增加了大量新特性,如自动类型推导、智能指针、Lambda表达式、并发编程等,使得C++变得更加现代化和易用。
  • C++14标准:2014年,发布了C++14标准,这是对C++11的一些小修订和改进。
  • C++17标准:2017年,发布了C++17标准,引入了一些新特性,例如文件系统库、并行STL、变量模板、constexpr if等。
  • C++20标准:2020年,发布了C++20标准,增加了概念(Concepts)、协程(Coroutines)、范围概述(Ranges)、模块(Modules)等重磅特性,进一步增强了C++的灵活性和强大性。

虽说现在已经更新到20了,但是有些版本只是小改动,像11,17,20这样的版本才更新了不少实用的新功能。但是实际上由于多方因素,最新的版本也不会大范围被快速使用,存在一定的滞后性,况且C++上手也有一定难度,前面的就够吃一壶的了,学习成本比较高。

再者就是编译器对新版本是否支持
编译器是否支持
主流的编译器有:GCCClangMSVC,其中 GCC 就是在 Linux 中使用的编译器,基本上 GCC 4.6 及后续版本就能对 C++11 进行很好的支持,而 MSVC 是微软 VS 系列的编译器从 VS 2015 及后续版本对C++11 语法支持较好

统一的列表初始化

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

初始化

C++11 中对 { } 进行了全面升级,使其不仅能初始化数组,还能初始化内置类型,用户定义的自定义类型以及 STL 中的容器的初始化

对内置类型

内置类型

  • 注意C++11之后初始化变量采用{}时,可以不加=符号; 但是可读性不是很好,不推荐。

有了C++11后的{},map的插入操作就会简洁很多。
map插入

实际上,{}的升级其实并不是什么新鲜事,其本质就是调用了构造函数。

如下面的日期类:
类对象在实例化时会自动调用构造函数初始化

Date d1(2024, 10, 12);

而d2这种写法实际上进行了隐式类型转化,采用了构造加赋值;先构造一个无名对象,再赋值

Date d2 = { 2024, 10, 12 };

如果要禁止隐式类型转化,在构造函数前面加上关键字explicit,这样就能禁止隐式类型转化了
禁止转化
此时的d3为C++11{}升级后的写法,发现不受隐式类型转化的影响

虽说使用{}初始化时,可以不用=,那d2,d3不应该是一样的吗?需要注意的是上述的d1,d2,d3中只有d3是C++11之后才支持的写法,d1,d2是C++11之前就支持的语法,且语言是有向前性的,所以此处d2的写法并不是11之后的写法

Date d3{ 2024, 10, 12 };//升级后的{},不需要进行隐式类型转化

所以{}的升级支持内置,自定义类型的初始化实际上就是通过构造函数实现的。

构造

构造函数

initializer_list

上面介绍了{}对内置类型,用户定义的自定义类型的升级;而C++11过后{}对 STL 中的容器的初始化也进行了升级,使得容器的初始化更加得心应手。

介绍使用前先了解initializer_list,initializer_list是一个类模板,提供以下成员函数:

  • 提供了begin和end函数,用于支持迭代器遍历。
  • 以及size函数支持获取容器中的元素个数

initializer_list
如:下面就是一个initializer_list

auto il1 = { 1,2,3,4,5,6 };

使用typeid查看il1的类型

typeid(il1).name()

可以看到编译器会自动识别{}里面的元素类型,此时类模板initializer_list的类型已经推导出来为int
typeid

具体细节请参考——initializer_list参考文档

使用场景

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

	list<string> l1 = { "huawei","apple","xiaomi","oppo" };//构造函数l1 = { "vivo","redmi" };//赋值

注意:
需要区分initializer_list与构造函数的迭代器区间构造:

    //构造函数的迭代器区间构造int arr[] = { 1,2,3,4,5,6,7,8,9 };vector<int>v2(arr, arr+sizeof(arr) / sizeof(int));
  • initializer_list是在{}中添加任意多个同类型元素,大小是任意的。
  • 迭代器区间构造需要指明出区间范围,也就是大小是固定的。

C++11之后,各大容器也都新增了该构造函数接口
vector

list
map
要实现该接口也简单,借助std里的initializer_list,再利用范围for将元素添加到容器中即可。如:在list中添加该接口。

		list(initializer_list<T> il){list_init();for (const auto& e : il){push_back(e);}}

声明

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

auto

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

使用

int TestAuto()
{return 10;
}int main()
{int a = 10;auto b = a;auto c = 'a';auto d = TestAuto();cout << typeid(b).name() << endl;cout << typeid(c).name() << endl;cout << typeid(d).name() << endl;//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化return 0;
}
  • typeid是一个运算符,它用于在运行时确定一个对象的类型信息

注意事项:

  • 使用auto定义变量时必须对其进行初始化, 在编译阶段编译器需要根据初始化表达式来推导auto的实际类型因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。
  • 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。
	auto a = 1, b = 2;auto c = 3, d = 4.0;  // 该行代码会编译失败,因为c和d的初始化表达式类型不同
  • auto不能作为函数的参数
//错误示例:参数无法推导
void TestAuto(auto a)
{}
  • auto不能直接用来声明数组
//错误示例
void TestAuto()
{int a[] = { 1,2,3 };auto b[] = { 4,5,6 };
}

auto在使用模板时会提供很大的便捷性,如使用map的迭代器

例如获取map的普通迭代器,如果要自己一五一十的写类型,就需要像it2一样,但是有了auto就可以让编译器自己推导了。

int main()
{std::map<string, string> m;auto it1 = m.begin();std::map<string, string>::iterator it2 = m.begin();cout << typeid(it1).name() << endl;cout << typeid(it2).name() << endl;return 0;
}

通过typeid查看迭代器类型,可以看到it1it2类型是一致的

auto

decltype

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

// decltype的一些使用使用场景
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的类型是doubledecltype(&x) p;      // p的类型是int*cout << typeid(ret).name() << endl;cout << typeid(p).name() << endl;F(1, 'a');//ascii可以转为intreturn 0;
}

decltype的使用需要指定推导的类型比auto麻烦一点。根据场景选择合适的就好。

nullptr

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

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

所以C++中使用空指针就用nullptr。

范围for

使用:
范围for
该语法就是使用auto自动推导所要访问的数据,紧接着编译器会自己去使用该容器所提供的迭代器(访问方式)去访问数据。

  • 数组天生就支持随机访问。

int main()
{int arr[] = { 1,2,3,4,5,6,7 };for (auto e : arr){cout << e << " ";}cout << endl;vector<int> v= { 1,2,3,4,5,6,7 };for (auto e : v){cout << e << " ";}cout << endl;set<int> s = { 1,2,3,4,5,6,7 };for (auto e : s){cout << e << " ";}cout << endl;return 0;
}

语法糖范围for用起来感觉很爽,其底层实际上也是编译器调用迭代器实现的。下面就是模拟string实现时,查看汇编发现范围for其实就是对迭代器的一层封装。
范围for

容器新增接口

C++11对容器新增了一些接口

emplace

可以看到常用的容器中基本都增加了emplace系列的接口,其用法我们稍后介绍。

vector

emplace

list

emplace

map

emplace

容器的新方法

下列为C++11后容器新增的一些方法。
push_back

push_back

构造

构造

这一系列的接口需要涉及新的知识点——右值引用和移动语义,都说这些接口能提高效率,那么是怎么做到的呢?让我们下回见真章。

关于C++11后容器的一些变化可以自行查阅——STL的相关调整,凡是有C++11这样标志的说明就是C++11才更新的新特性。

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

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

相关文章

#HarmonyOS:页面和自定义组件生命周期

页面生命周期 即被Entry装饰的组件生命周期 onPageShow&#xff1a;页面每次显示时触发一次&#xff0c;包括路由过程、应用进入前台等场景。onPageHide: 页面每次隐藏时触发一次&#xff0c;包括路由过程、应用进入后台等场景。onBackPress: 当用户点击返回按钮是触发 组件…

成都睿明智科技有限公司解锁抖音电商新蓝海

在这个短视频风靡的时代&#xff0c;抖音已不仅仅是一个娱乐平台&#xff0c;它更是商家们竞相追逐的电商新战场。成都睿明智科技有限公司&#xff0c;作为抖音电商服务领域的佼佼者&#xff0c;正以敏锐的洞察力和专业的服务&#xff0c;助力众多品牌在这片蓝海中乘风破浪&…

RHCE-多IP访问网站

关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0下载nginx工具 [rootlocalhost ~]# yum install nginx Updating Subscription Management repositories. Unable to read consumer identityThis system is not registered with an …

面对AI算力需求激增,如何守护数据中心机房安全?

随着人工智能&#xff08;AI&#xff09;技术飞速发展&#xff0c;AI算力需求呈现爆发式增长&#xff0c;导致对数据设备电力的需求指数级攀升。这给数据中心带来前所未有的挑战和机遇&#xff0c;从提供稳定的电力供应、优化高密度的部署&#xff0c;到数据安全的隐私保护&…

【unity小技巧】Unity6 LTS版本安装和一些修改和新功能使用介绍

文章目录 前言安装新功能变化1、官方推荐使用inputsystem进行输入控制2、修复了InputSystem命名错误导致listen被遮挡的bug3、自带去除unity启动画面logo功能4、unity官方的behavior行为树插件5、linearVelocity代替过时的velocity方法待续 完结 前言 2024/10/17其实unity就已…

前端拦截302重定向

背景: 根据业务场景需要拦截302做后续的逻辑处理 尝试一: : axios拦截 、、、、、async created() {// 获取302请求返回的location后手动修改video的src路径let targetSrc;try {await axios.get(this.video).then((res) > {const { headers, status } res;const { locat…

Spring Cloud 解决了哪些问题?

大家好&#xff0c;我是锋哥。今天分享关于【Spring Cloud 解决了哪些问题&#xff1f;】面试题&#xff1f;希望对大家有帮助&#xff1b; Spring Cloud 解决了哪些问题&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Spring Cloud 是一个为构建分布式…

如何删除Maven

1.找到Maven安装路径 方法一&#xff1a; 可以直接在文件资源管理器里面选中“此电脑”然后右上角搜“apache-maven”&#xff0c;这个过程可能长达几分钟甚至更久 方法二&#xff1a; 这里推荐一个名叫“Everything”的软件&#xff0c;能够快速的查找到需要的文件 2.找到本…

每日一道算法题(Leetcode 20)

Whats past is prologue. 凡是过去&#xff0c;皆为序章。 题目 分析 1. 我们可以用栈的结构来解决这道题。 2. 我们使用while循环&#xff0c;每次读取字符串中一个元素进行操作&#xff0c;直到最后读取到 \0为止。 3. 如果遇见 (, [ ,{ 这三种左括号&#xff0c;则把该左…

【AIGC】AI如何匹配RAG知识库:关键词搜索

关键词搜索 引言jieba库简介TF-IDF简介实践例子用jieba库提取关键词计算TF-IDF计算文档和查询相似度结果完整代码&#xff1a; 总结 引言 RAG作为减少模型幻觉和让模型分析、回答私域相关知识最简单高效的方式&#xff0c;我们除了使用之外可以尝试了解其是如何实现的。在实现…

写一个自动采集地球前30行业的小程序

创建一个自动采集地球前30行业信息的小程序可以使用Python和一些常用的库&#xff0c;如BeautifulSoup和Requests。以下是一个基本示例&#xff0c;展示如何从网页上抓取行业信息&#xff1a; 环境准备 安装Python&#xff1a;确保你的计算机上已安装Python。安装库&#xff…

电影评论网站开发:Spring Boot技术指南

3系统分析 3.1可行性分析 通过对本电影评论网站实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本电影评论网站采用SSM框架&#xff0c;JAVA作为开发语言&#…

从传统到智能,从被动监控到主动预警,解锁视频安防平台EasyCVR视频监控智能化升级的关键密钥

视频监控技术从传统监控到智能化升级的过程是一个技术革新和应用场景拓展的过程。智能视频监控系统通过集成AI和机器学习算法&#xff0c;能够实现行为分析、人脸识别和异常事件检测等功能&#xff0c;提升了监控的准确性和响应速度。这些系统不仅用于传统的安全防护&#xff0…

【linux009】文件操作命令篇 - touch 命令

文章目录 touch 命令1、基本用法2、常见选项3、举例4、注意事项 touch 命令 touch 是 Linux 系统中的一个常用命令&#xff0c;用于创建空文件或更新已有文件的时间戳。它既可以用来快速生成新文件&#xff0c;也可以用来修改文件的访问时间&#xff08;access time, atime&am…

react18中如何监听localstorage的变化获取最新的本地缓存

有时候业务中会需要监听缓存的变化&#xff0c;实时更新页面的内容获取发送接口请求。这就要我们来监听对localstorage的修改&#xff0c;实时响应变化&#xff01;&#xff01;一下方法同样实用于vue项目。 同一个项目中不同页面的实现 实现效果 代码分析 修改localstoare的…

【算法】KMP算法

写在前面 在学习KMP算法前&#xff0c;不才也曾在众多博客中阅读过KMP算法的文章&#xff0c;但是都看得迷迷糊糊&#xff0c;所以不才在学透了KMP算法后&#xff0c;详细编写了这篇笔记&#xff0c;希望对你有帮助&#x1f970;&#x1f970;。 KMP算法的核心思想不分任何语…

二叉树习题其二Java【力扣】【算法学习day.9】

前言 前言 书接上篇文章二叉树习题其一&#xff0c;这篇文章我们将基础拓展 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思…

云计算第四阶段-----CLOUND二周目 04-06

cloud 04 今日目标&#xff1a; 一、Pod 生命周期 图解&#xff1a; [rootmaster ~]# vim web1.yaml --- kind: Pod apiVersion: v1 metadata:name: web1 spec:initContainers: # 定义初始化任务- name: task1 # 如果初始化任务失败&#…

目前最新 dnSpy V6.5.1版本,最好的 .NET 程序调试、编辑、反编译软件

目前最新 dnSpy V6.5.1版本&#xff0c;最好的 .NET 程序调试、编辑、反编译软件 一、 简介二、新发布程序更新功能三、官方下载&#xff1a; 一、 简介 dnSpy 是一个调试器 .NET 程序集的编辑器。即使没有源代码&#xff0c;也可以使用它来编辑和调试程序集。主要特点&#x…

连锁收银系统

商淘云连锁管理系统助力连锁企业实现“人货账”全方位数字化管理&#xff0c;它依托连锁品牌进销存管理实现门店订货、线下收银、线上商城、会员营销等一体化管理。 门店订货补货支持连锁直营、加盟 不同门店不同进货价、不同门店不同商品、不同门店在线或者账期支付、门店PC或…