【C++11(一)之入门基础)】

news2024/11/14 17:23:28

文章目录

  • C++简介
  • 统一的列表初始化
      • {}初始化
  • std::initializer_list
      • std::initializer_list是什么类型:
      • std::initializer_list使用场景:
  • 声明
      • auto
      • decltype
      • nullptr
  • STL中一些变化

C++简介

在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增加的语法特性非常篇幅非常多,我们这里没办法一 一讲解,所以本节课程主要讲解实际中比较实用的语法。
https://en.cppreference.com/w/cpp/11
小故事
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中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。比如:

struct Point
{
	int x;
	int y;
};
int main()
{
	int array[] = { 1, 2, 3, 4, 5 };
	int array[5] = { 0 };
	Point p = { 1, 2 };
	return 0;
}

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

int main()
{
	//C++11 内置类型支持列表初始化
	int a = 0;
	//不推荐
	int b = { 1 };
	int c{ 1 };	//可以省略=
	//C++11 列表初始化也可适用于new表达式中
	int* pa = new int[5] {0};
	return 0;
}

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

class Date
{
public:
	Date(int year, int month, int day)
		:_year(year)
		,_month(month)
		,_day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
//一切皆可列表初始化
int main()
{
	//C++98 构造
	//多差数
	Date d1(2024, 3, 23);
	//C++11
	//构造 + 拷贝构造-》优化-》直接构造
	//多参数的隐式类型转换
	// C++11支持的列表初始化,这里会调用构造函数初始化
	Date d2 = { 2024, 3, 23 };
	Date d3{ 2023, 3, 23 };
	//单参数
	string s1("1111");//构造
	string s2 = "1111";	//单参数隐式类型转换
	//new表达式也可列表初始化
	Date* darr1 = new Date[3]{ d1, d2, d3 };
	Date* darr2 = new Date[3]{ {2023, 3, 4}, {2024, 3, 23}, {2024, 3, 24} };
}

std::initializer_list

std::initializer_list是什么类型:

int main()
{
	auto il1 = { 1, 2,3,4, 5 };
	cout << typeid(il1).name() << endl;//class std::initializer_list<int>
}

具体查看一下:
在这里插入图片描述
在这里插入图片描述

可以发现initializer_list其实就是一个模板类,且成员函数支持begin,end说明其支持迭代器,也就支持范围for,还有size接口提供其大小。

std::initializer_list使用场景:

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

int main()
{
	initializer_list<int>il1 = { 1, 2, 3,4,5 };
	initializer_list<int>il2 = { 1, 2, 3,4,5 ,6,7,8,9,10};
	cout << sizeof(il1) << endl;	//16
	cout << sizeof(il2) << endl;	//16
}

从代码结果大小来看,其实initializer_list底层就是有两个begin,end两个指针,指向这n个相同类型参数,编译器会将其存到静态区的一个数组空间里面的首和尾。

C++11支持一系列容器进行列表初始化,那正如上面所说,自定义类型可以单参数或者多参数隐式类型转换,也就是列表初始化去调用构造函数,这里容器列表初始化有n个相同类型的参数,怎么办呢?

int main()
{
	//C++11 容器也支持列表初始化
	vector<int> v1 = { 1, 2, 3, 4, 5, 6 };
	vector<int> v2;
	v2 = { 1, 2, 3 };
	for (auto e : v1)
	{
		cout << e << " ";
	}
	pair<string, string> kv1("sort", "排序");
	pair<string, string> kv2("string", "字符串");
	map<string, string> dict1 = { kv1, kv2 };	//写法一
	map<string, string> dict2 = { {"sort", "排序"}, {"string", "字符串"} };	//写法二
	for (auto& kv : dict2)
	{
		cout << kv.first << ":" << kv.second << endl;
	}
	pair<const char*, const char*> kv3("sort", "排序");
	pair<const string, string> kv4(kv3);
	return 0;
}

解释一:
vector容器可以进行列表初始化,原因是支持了initializer_list作为参数的构造函数,vector容器对象可以使用列表初始化进行赋值,也是增加了initializer_list作为参数的operator=函数。
在这里插入图片描述
在这里插入图片描述
解释二:

map<string, string> dict2 = { {"sort", "排序"}, {"string", "字符串"} };	

对于每个pair使用列表初始化还能理解,map使用列表初始化也能理解,无非就是调用了C++11新增加的initializer_list作为参数的构造函数嘛为什么对于pair列表初始化时,pair是pair<const char*, const char*>类型,怎么到了initializer_list这里,就变成了initializer_list<pair<const string, string>类型呢?
原因如下:

template<class T1, class T2>
struct pair
{
	//pari<const char*, const char*> kv3
	pair(const T1& t1, cosnt T2& t2)
		:first(t1)
		,second(t2)
	{}
	//pair<const string, string>kv4(kv3)
	//新玩法,新场景,拷贝构造实现模板
	template<class U, class V>	
	pair(pair<U, V>& kv)
	{
		first = kv.first;	
		second = kv.second;
	}
private:
	T1 first;
	T2 second;
};

通过增加pair的模板拷贝构造函数就解决了。

声明

auto

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

//切记auto 不能用于函数的返回值
auto func2()
{
	return 2;
}
int fun()
{
	return 1;
}
int main()
{
	int i = 10;
	auto p = &i;
	auto pf = fun;
	cout << typeid(pf).name() << endl;
	cout << typeid(p).name() << endl;
	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	cout << typeid(it).name() << endl;
	return 0;
}

切记:auto不要用于函数返回值,尽管C++20之后支持

decltype

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

int func()
{
	return 10;
}
int main()
{
	const int x = 1;
	const int* p1 = &x;
	decltype(p1) p2 = nullptr;
	cout << typeid(p2).name() << endl;
	//使用场景
	auto ret = func();
	//假设需要用vector存func的数据
	vector<decltype(ret)> v;
	return 0;
}

作用就是取出原生类型

nullptr

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

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

STL中一些变化

新容器

一、array容器
array容器本质就是一个静态数组,即固定大小的数组。

array容器有两个模板参数,第一个模板参数代表的是存储的类型,第二个模板参数是一个非类型模板参数,代表的是数组中可存储元素的个数。比如:

int main()
{
	array<int, 10> a1;   //定义一个可存储10个int类型元素的array容器
	array<double, 5> a2; //定义一个可存储5个double类型元素的array容器
	return 0;
}

array容器与普通数组对比:

  • array容器与普通数组一样,支持通过[]访问指定下标的元素,也支持使用范围for遍历数组元素,并且创建后数组的大小也不可改变。
  • array容器与普通数组不同之处就是,array容器用一个类对数组进行了封装,并且在访问array容器中的元素时会进行越界检查。用[]访问元素时采用断言检查,调用at成员函数访问元素时采用抛异常检查。
  • 而对于普通数组来说,一般只有对数组进行写操作时才会检查越界,如果只是越界进行读操作可能并不会报错。

但array容器与其他容器不同的是,array容器的对象是创建在栈上的,因此array容器不适合定义太大的数组。

二、forward_list容器
forward_list容器本质就是一个单链表。

forward_list很少使用,原因如下:

  1. forward_list只支持头插头删,不支持尾插尾删,因为单链表在进行尾插尾删时需要先找尾,时间复杂度为O(N)。
  2. forward_list提供的插入函数叫做insert_after,也就是在指定元素的后面插入一个元素,而不像其他容器是在指定元素的前面插入一个元素,因为单链表如果要在指定元素的前面插入元素,还要遍历链表找到该元素的前一个元素,时间复杂度为O(N)。
  3. forward_list提供的删除函数叫做erase_after,也就是删除指定元素后面的一个元素,因为单链表如果要删除指定元素,还需要还要遍历链表找到指定元素的前一个元素,时间复杂度为O(N)。

因此一般情况下要用链表我们还是选择使用list容器。

三、unordered_map和unordered_set容器
unordered_map和unordered_set容器底层采用的都是哈希表。
C++11提供了各种内置类型与string之间相互转换的函数,比如to_string、stoi、stol、stod等函数。

容器中的一些新方法

  1. 提供了一个以initializer_list作为参数的构造函数和赋值函数,用于支持列表初始化。
  2. 提供了cbegin和cend方法,用于返回const迭代器。无关痛痒
  3. 提供了emplace系列方法,并在容器原有插入方法的基础上重载了一个右值引用版本的插入函数,用于提高向容器中插入元素的效率。
  4. push_xxx , insert ,增加了右值引用版本,意义重大。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

报告 | 以消费者为中心,消费品零售行业数字化建设持续深化

​2024年是“消费促进年”&#xff0c;国内消费市场稳步复苏。在消费需求多样化、国家政策的推动下&#xff0c;“数字化转型”仍是消费品零售行业的年度主题词&#xff0c;是品牌方获取核心竞争力的必要途径。消费品零售行业的数字化转型重心有所调整&#xff0c;从线上渠道布…

ARM架构

一、内存分布结构 栈&#xff1a;局部变量 函数参数 函数返回地址 堆&#xff1a;程序员自己管理的内存区域&#xff0c;使用是需要动态申请&#xff0c;使用捷顺后需要释放 bss&#xff1a; 初始化为0和未初始化的全局及静态变量 data&#xff1a;初始化不为0全局及静态变量…

Opencv中的直方图(4)局部直方图均衡技术函数createCLAHE()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 创建一个指向 cv::CLAHE 类的智能指针并初始化它。 函数原型 Ptr<CLAHE> cv::createCLAHE (double clipLimit 40.0,Size tileGridSize…

JavaScript的BOM模型

一、浏览器环境概述(BOM) JavaScript 是浏览器的内置脚本语言&#xff0c;一旦网页内嵌了 JavaScript 脚本&#xff0c;浏览器加载网页&#xff0c;就会去执行脚本&#xff0c;从而达到操作浏览器的目的&#xff0c;实现网页的各种动态效果 二、script 元素工作原理 浏览器加…

网络编程 0903作业

作业 1、将TCP的CS模型再敲一遍 tcpserver.c #include <myhead.h> #define SERPORT 1111 #define SERIP "192.168.58.128" #define BACKLOG 40 int main(int argc, const char *argv[]) {int oldfd socket(AF_INET,SOCK_STREAM,0);//1、产生一个原始套接字…

pikachu文件包含漏洞靶场

File inclusion(local) 创建1.php 步骤一&#xff1a;选择一个球员提交 ../../../../1.php File Inclusion(remote)&#xff08;远程文件包含&#xff09; 步骤一&#xff1a;更改参数 php.ini ⾥有两个重要的参数 allow_url_fopen 、allow_url_include &#xff1b; 步骤二…

玩机进阶教程-----如何通过boot查看当前机型版本号 型号以及启动分区 提升保资料写固件成功率

在玩机过程中我们会遇到一些无法开机进系统的机型。而有需要其中的数据。如果简单的写入固件。可能会由于与当前机型版本不符或者版本差别太大的缘故而导致资料无法保存。如果当前机型有版本仿回滚机制。那么有可能误刷系统也会不开机。那么如何通过简单的操作来查看当前机型的…

GAMES202——作业5 实时光线追踪降噪(联合双边滤波、多帧的投影与积累、À-Trous Wavelet 加速单帧降噪)

任务 1.实现单帧降噪 2.实现多帧投影 3.实现多帧累积 Bonus:使用-Trous Wavelet 加速单帧降噪 实现 单帧降噪 这里实现比较简单&#xff0c;直接根据给出的联合双边滤波核的公式就能实现 Buffer2D<Float3> Denoiser::Filter(const FrameInfo &frameInfo) {int heigh…

科研小白教程|如何远程连接实验室服务器跑代码?

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a; 【计算机系统架构】从0开始构建一台现代计算机|时序逻辑、主存储器|第3章每日一言&#x1f33c;: 总之岁月漫长&#xff0c;然而值得等待。—…

国内可以免费使用的gpt网站【九月持续更新】

GPT Hub 是我最近使用的一款智能文本生成工具平台&#xff0c;它支持多种AI模型&#xff0c;包括最新的GPT-4模型&#xff0c;并且可以在国内网络环境中直接访问。以下是我在使用过程中发现的一些特点&#xff1a; 多功能支持&#xff1a;不仅支持代码生成&#xff0c;还涵盖了…

【主机入侵检测】Wazuh解码器之JSON解码器

前言 Wazuh 是一个开源的安全平台&#xff0c;它使用解码器&#xff08;decoders&#xff09;来从接收到的日志消息中提取信息。解码器将日志信息分割成字段&#xff0c;以便进行分析。Wazuh 解码器使用 XML 语法&#xff0c;允许用户指定日志数据应该如何被解析和规范化。解码…

Java基础(10)- 学生管理系统项目

一、JavaBean编写 public class Student {private int id;private String name;private int age;private String sex;public Student() {}public Student(int id, String name, int age, String sex) {this.id id;this.name name;this.age age;this.sex sex;}public int g…

绝对定位导致内容自动换行问题解决

今天在做一个定位元素的时候遇到一个嵌套定位之后&#xff0c;使用绝对定位的元素的内容自动换行的问题&#xff0c;希望不换行只在一行显示。 可以通过添加 white-space: nowrap; 样式控制不换行 <div class"box"><div class"box1"><div …

深入剖析:中国国际大学生创新大赛中不可忽视的12个扣分点

深入剖析&#xff1a;中国国际大学生创新大赛中不可忽视的12个扣分点 前言1. 项目名称&#xff1a;第一印象的力量2. 项目逻辑&#xff1a;清晰的思路是关键3. 问题分析&#xff1a;深入挖掘痛点4. 需求分析&#xff1a;解决方案的导向5. 科研课题与评审维度的匹配6. 团队介绍&…

DataWhale AI夏令营-《李宏毅深度学习教程》笔记-task3

DataWhale AI夏令营-《李宏毅深度学习教程》笔记-task2 第五章 循环神经网络5.1 独热编码5.2 RNN架构5.3 其他RNN5.3.1 Elman 网络 &Jordan 网络5.3.2 双向循环神经网络 第五章 循环神经网络 循环神经网络RNN&#xff0c;RNN在处理序列数据和时间依赖性强的问题上具有独特…

渗透测试靶机--- DC系列 DC-6

渗透测试靶机— DC系列 DC-6 开启靶机&#xff0c;登录页面&#xff0c;平平无奇 扫描ip&#xff0c;端口&#xff0c;服务等信息 访问80&#xff0c;发现这里是WordPress站点 直接wpscan扫描一下用户名wpscan --url http://wordy -e u 这里可以将扫出来的五个用户名保存&…

WPF性能优化之UI虚拟化

文章目录 前言一、VirtualizingStackPanel1.1 虚拟化功能介绍1、在Window中添加一个ListBox控件。2、在设计视图中用鼠标选中ListBox控件并右健依次单击“编辑其他模板”&#xff0d;“编辑项的布局模板”&#xff0d;“编辑副本”。3、查看生成的模板代码。 1.2 虚拟化参数介绍…

如何提升网站权重?

提升网站权重的方法有很多&#xff0c;常规的方法包括内容优化、关键词研究、页面结构调整、提高用户体验等。但这些方法往往需要时间来见效。如果你希望在短时间内看到显著的提升&#xff0c;发外链是一个非常有效的策略。 外链是提升网站权重的有效方法&#xff0c;但需要注…

9月3c++

封装栈和队列 队列 #include <iostream> #include <cstring> using namespace std; class Myqueue { private:int data[256];int size0; public:Myqueue(){}//无参构造~Myqueue(){}//析构//拷贝赋值Myqueue & operator(const Myqueue &other){if(this!&a…

C++ ─── List的模拟实现

一&#xff0c; List的模拟实现 List 是一个双向循环链表,由于List的节点不连续&#xff0c;不能用节点指针直接作为迭代器&#xff0c;因此我们要对结点指针封装&#xff0c;来实现迭代器的作用。 迭代器有两种实现方式&#xff0c;具体应根据容器底层数据结构实现&#xff1…