【C++】C++11——简介|列表初始|简化声明|nullptr与范围for|STL中的变化

news/2025/3/30 16:24:49/

文章目录

    • 一、C++11简介
    • 二、列表初始化
    • 三、简化声明
    • 四、nullptr与范围for
    • 五、STL中一些变化

一、C++11简介

在2003年C++标准委员会曾经提交了一份技术勘误表(简称TC1),使得C++03这个名字已经取代了C++98称为C++11之前的最新C++标准名称。不过由于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++98中,标准允许使用花括号{}对数组元素进行统一的列表初始值设定。举个例子:

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

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

struct Point
{int _x;int _y;
};
int main()
{Point p1 = { 1,2 };int array1[] = { 1,2,3,4,5 };//去掉赋值符号Point p2{ 2,2 };int array2[]{ 1,2,3,4,5 };//更加离谱int x1 = 1;int x2 = { 1 };int x3{ 1 };return 0;
}

new 表达式初始化时一定不能添加等号:

int* p3 = new int[10];int* p4 = new int[10]{ 1,2,3,4 };
Point* p5 = new Point[2]{ {1,1},{2,2} };

日期类构造函数初始化:

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(1, 1, 1);//构造函数Date d2{ 1,1,1 };return 0;
}

对于上面这些都是比较轻松的,更多的在于容器的初始化:

int main()
{vector<int> v = { 1,2,3,4,5,6,7,8};vector<int> v1 = { 1,2,3,4 };list<int> lt = { 1,2 };list<int> lt1 = { 1,2,3,4,5,6,7 };return 0;
}

vector和list为什么可以这样子初始化,这就要说到一个新的容器了:initializer_list

initializer_list 是一个容器,是 C++11 新增的:

只提供了 begin 和 end 函数,用于迭代器遍历;以及获取容器中的元素个数的 size 函数:

image-20230306234037072

{}的本质就是initializer_list,如果我们使用auto来定义一个变量去接收一个大括号括起来的列表,然后用 typeid(变量名).name() 查看变量的类型,此时会发现该变量的类型就是 initializer_list👇

image-20230306233627590

这个东西到底有什么用:C++98 不支持直接用列表对容器进行初始化,这种初始化方式是在C++11引入initializer_list后才支持的,而这些容器之所以支持使用列表进行初始化,是因为C++11提供了一个构造函数,以initializer_list为参数

看一下C++11vector的构造:

image-20230307123009003

image-20230307124624643

当用列表对容器进行初始化时,会被认为是initializer_list类型,此时不管有多少个值都能够被初始化vector。而我们之前自己实现的vector是无法支持的,现在我们可以为之前自己模拟实现的vector提供一个构造函数:遍历initializer_list 中的元素,然后push_back进要初始化的容器当中:

vector(initializer_list<T> il):_start(nullptr), _finish(nullptr), _endofstorage(nullptr)
{typename initializer_list<T>::iterator it = il.begin();while (it != il.end()){push_back(*it);++it;}
}

三、简化声明

C++11提供了多种简化声明的方式。

1.auto

auto使用的前提是:必须要对auto声明的类型进行初始化,否则编译器无法推导出auto的实际类型。

如果类型过长,比如迭代器的名称,我们就可以使用auto,用于实现自动类型推断

int main()
{int x = 0;auto y = x;cout << typeid(x).name() << endl;cout << typeid(y).name() << endl;return 0;
}

image-20230307131053460

typeid只能查看类型不能用其结果类定义类型

2.decltype

decltype是根据表达式的实际类型推演出定义变量时所用的类型

template<class T1, class T2>
void F(T1 t1, T2 t2)
{decltype(t1 * t2) ret = t1 * t2;cout << typeid(ret).name() << endl;cout << ret << endl;
}int main()
{int x = 0;decltype(x) y;cout << typeid(y).name() << endl;F(1, 2.2);
}

image-20230307132004655

typeid(变量名).name()的方式只能获取一个变量的类型,但无法获取这个类型去定义变量。而decltype除了能够推演表达式的类型,还能推演函数返回值的类型。


四、nullptr与范围for

  • nullptr

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

#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else  
#define NULL    ((void *)0)
#endif  
#endif  /* NULL */
  • 范围for

C++11中还有范围for,范围for循环后的括号由冒号分为两部分,第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围:

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

范围for本质上是由迭代器支持的,在代码编译的时候,编译器会自动将范围for替换为迭代器的形式


五、STL中一些变化

C++11中新增了容器,分别是array、forward_list、unordered_map和unordered_set

image-20230308124304812

  • array

array是一个静态数组,即固定大小的数组,没有资格与vector对比:

array有两个模板参数,第一个模板参数代表的是存储的类型,第二个模板参数是一个非类型模板参数,代表数组中存储元素个数

int main()
{array<int,10> a1;int a2[10];a2[11];//没报错return 0;
}

array与普通数组的对比:

C语言数组对于越界检查是抽查的,越界可能检查不出来,但是对于array的越界读写都能检查出来的

因为array用一个类对数组做了封装,并且在访问array容器中的元素时会进行越界检查:用[]访问元素时采用断言,调用at成员函数访问元素时采用抛出异常检查。

当然,vector也可以检查出越界的情况,而且array没有初始化,并且与其他容器不同的是,array容器的对象是创建在栈上的,因此array容器不适合定义太大的数组,不如vector

  • forward_list容器

image-20230308132352601

forward_list容器本质就是一个单链表,很少使用:

image-20230308174418028

forward_list只提供了头插头删,不支持尾插尾删,因为单链表在进行尾插尾删时需要先找尾

forward_list提供插入insert_after在指定的元素后面插入一个元素,而不像其他容器是在指定的元素前面插入一个元素,单链表要找到指定元素前一个元素就要重新遍历一遍,删除也是erase_after,也就是删除指定元素后的一个。

所以我们一般还是使用list容器

  • C++11新的接口

C++11给容器都增加了一些新的接口:

最开始说的提供了一个以initializer_list作为参数的构造函数,用于支持列表初始化

比较鸡肋的接口:cbegin 、cend系列,以及缩容接口shrink_to_fit(异地)

比较有用:

移动构造和移动赋值

emplace_xxx插入接口


本篇结束…


http://www.ppmy.cn/news/30962.html

相关文章

MATLAB的快速入门

第一部分&#xff1a;基础知识常用命令&#xff1a;clc %清除命令行窗口 clear %清空工作区数据 cd %显示或改变工作目录 clf %清除图形窗口 help %打开帮助文档 save %保存内存变量到指定文件 hold %保持图形 close %关闭当前图窗 quit %退出变量&#x…

Lesson 8.3 ID3、C4.5 决策树的建模流程 Lesson 8.4 CART 回归树的建模流程与 sklearn 参数详解

文章目录一、ID3 决策树的基本建模流程二、C4.5 决策树的基本建模流程1. 信息值&#xff08;information value&#xff09;2. C4.5 的连续变量处理方法三、CART 回归树的基本建模流程1. 数据准备2. 生成备选规则3. 挑选规则4. 进行多轮迭代5. 回归树的预测过程四、CART 回归树…

【C语言】每日刷题 —— 牛客

前言 大家好&#xff0c;今天带来一篇新的专栏 c_牛客&#xff0c;不出意外的话每天更新十道题&#xff0c;难度也是从易到难&#xff0c;自己复习的同时也希望能帮助到大家&#xff0c;题目答案会根据我所学到的知识提供最优解。 &#x1f3e1;个人主页&#xff1a;悲伤的猪大…

GMPC认证有哪些内容?

【GMPC认证有哪些内容?】GMP(GMP Good Manufacturing Practice)即良好生产规范&#xff0c;最早是美国国会为了规范药品生产而于1963年颁布的。这也是世界上第一部GMP。由于GMP在规范药品的生产&#xff0c;提高药品的质量&#xff0c;保证药品的安全方面效果非常明显&#xf…

跟ChatGPT学量化,菜鸟炒股也不怕

你是一个python资深量化开发工程师&#xff0c;请介绍量化交易的基本框架 量化交易的基本框架包括以下几个步骤&#xff1a; 数据获取&#xff1a;获取市场数据和公司财务数据等&#xff0c;可以使用API接口、爬虫等方式获取。数据清洗和预处理&#xff1a;对获取到的数据进行清…

项目实战典型案例8——让软件的使用者成为软件的设计者

让软件的使用者成为软件的设计者一&#xff1a;背景介绍二&#xff1a;思路&方案公司的产品设计理念如果你设计的软件猪不能使&#xff0c;你就是猪让每一个软件的使用者都成为我们软件的设计者过程四&#xff1a;总结五&#xff1a;升华一&#xff1a;背景介绍 由于同时对…

Vue3手写分页在分页的基础上用到Pagination 分页组件

近期有个项目要用到分页组件&#xff0c;但是内容不是表格&#xff0c;所以自己就研究了一下在Pagination 分页组件的基础上手写了分页 效果图&#xff1a; 目录 一、先声明几个变量用来定义第几页&#xff0c;每页多少条&#xff0c;总页数。 二、然后封装一个函数方便以后…

小白做什么兼职项目赚钱?宝妈拍短视频赚钱的方法

很多宝妈在家带孩子之余想做兼职赚点小钱&#xff0c;依靠互联网无疑是比较方便的途径&#xff0c;在刷单、微商等网上兼职成为过去式以后&#xff0c;很多宝妈选择了短视频创业。 宝妈怎么拍短视频&#xff1f; 宝妈因为要照顾宝宝还要兼顾家务&#xff0c;空闲的时间比较琐碎…