【C++11新特性】统一列表初始化,声明,新增容器,lambda表达式

一、C++11简介

相比于C++98和C++03,C++11带来了数量可观的变化,其中包含了约有140种新特性,以及对C++03标准中约600个缺陷的修正,这使得C++11更像是一种从C++98/03中孕育出来的一种新的语言,C++11能更好的用于系统开发和库开发,语法更加泛化和简单化,更稳定安全,不仅功能强大,而且能提高程序员的开发效率。

二、列表初始化

1.引入

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

2.使用

2.1 内置类型与容器

	//内置类型初始化
	int x1 = { 10 };
	int x2{ 10 };//省略赋值符号
	int x5{ 1 + 2 };
	//数组
	int arr1[5]{ 1,2,3 };//后面也默认为0
	int arr2[]{ 1,2,3,4,5 };
	//动态数组
	int* arr3 = new int[5]{ 1,2,3,4,5 };
	//标准容器
	vector<int> v1{ 1,2,3,4 };
	v1 = { 4,5,6,7 };//支持赋值
	map<int, int> m{ {1,1},{2,2},{3,3} ,make_pair(4,4)};

2.2 自定义类型

struct point
{
	int _x;
	int _y;
	point(int x,int y):_x(x),_y(y)
	{
		cout << "调用了构造函数" << endl;
	}
};
point pp{ 2,2 };
point* ptr = new point[2]{ {1,1},{2,2} };//当没有构造函数时会兼容C语言的特性,当有构造函数时会调用构造函数

3.原理

统一初始化列表({})是一个initializer_list类型,在很多STL容器中,都提供了一个支持initializer_list类型构造函数:
在这里插入图片描述
在对操作符=进行重载的时候,也会有该类型对应的函数:
在这里插入图片描述

三、声明(decltype)

声明其实一共包括两部分,分别是auto自动推导类型,以及decltype自动推导类型+定义对象。auto在之前的章节里已经详细讲过,这里不多进行赘述。

	int func(int a)
	{
	return a;
	}
	int x;
	double y = 2.2;
	decltype(x) z = 2;//将z定义成和x一样的类型
	decltype(&x) p;//定义一个指针类型
	int(*pfunc1)(int) = func;//定义一个函数指针类型pfunc1指向func
	decltype(&func) pfunc3 = func;
	auto pfunc4 = func;//函数指针使用起来也非常方便,不过这里使用auto进行推导更加便捷
	//在vector定义类型的时候auto无法使用,decltype可以很好的帮助定义类型
	vector<int> v;
	vector<int>::iterator it = v.begin();
	vector<decltype(it)> vv;//这里可以使用decltype,但是无法使用auto
	vv.push_back(it);

注意decltype在推导函数指针类型的时候,需要加&符号。而不能将函数名就当做地址了。

四、新增STL容器

STL中新增加了一些容器,比如unordered_map和unordered_set等,还为这些容器增加了一些接口,比如列表的初始化,右值引用版本提高效率等。

1.array(静态数组)

	int a1[10];
	array<int, 10> a2;
	array<int, 10>::iterator it = a2.begin();//支持迭代器
	a1[14] = 0;//不会报错,是*(a1+14)
	a2[14] = 0;//会报错,是a2.operator[](14),是一个函数会有assert

array相较于直接定义数组而言,引入了迭代器更好的兼容STL的用法,并且有对越界的检测,因为它的[]底层是函数调用。

2.forward_list(单链表)

对于已经有了带头双向循环链表list来说,forward_list显得更加的鸡肋,它不支持头插头删(因为需要遍历到最后影响效率),当定点插入的时候会插入在元素的后面。(因为插入到前面需要再定义一个指向前一个节点的指针)。

3.STL所有容器

至此STL的所有容器介绍完毕:

STL属性
array静态数组
vector动态数组
deque双端队列
forward_list单链表
list双向带头循环链表
stack
queue队列
priority_queue优先级队列
setK结构红黑树
mapKV结构红黑树
mutiset可以有重复节点的set
mutimap可以有重复节点的map
unordered_setK结构哈希表
unordered_mapKV结构哈希表
unordered_multiset可以有重复节点的unordered_set
unordered_multimap可以有重复节点的unordered_map

五、lambda表达式

1.lambda表达式的构成与规则

[capture-list] (parameters)mutable->return-type{statement}

1.[capture-list]:捕捉列表,该列表出现在lambda的初始位置,编译器根据[]来判断界带来的代码是否是lambda表达式,捕捉列表能够捕捉上下文中的变量供lambda使用。其实只能捕获上文中数据。

[var]:表示获取某一个变量
[=]:获取上文的所有变量
[&var]:获取某一个变量的引用
[&]:获取上文变量的所有引用

2.(parameters):参数列表,与普通函数的列表一致,如果不需要参数穿肚,可以连同()一起省略。
3.mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性,使用该修饰符时,参数列表不可省略。
4.->return-type:返回值类型,用追踪返回形式声明函数的返回值类型,没有返回值(void)的时候可以将此部分省略。当返回值明确的情况下,也可以省略,由编译器对返回类型进行推导。
5.{statement}:函数体,和普通函数使用方法相同。
可以把它理解成一个匿名函数。注意,它只是一个函数定义,真正想要使用函数需要进行函数调用。

2.应用

	auto fun = [] {};//最简单lambda表达式
	auto add1 = [] (int a, int b)->int{return a + b; };
	auto add2 = [](int a, int b) {return a + b; };//省略返回值,让编译器自动推导
	cout << add1(1, 2) << endl;//和函数的调用方法相同
	cout << add2(2, 3) << endl;
	auto func = [] {cout << "hello lambda" << endl; };//没有参数
	func();
	int a = 10;
	int b = 20;
	auto swap1 = [](int& x, int& y)//和函数一样交换数据的时候必须带引用
	{
		int z = x;
		x = y;
		y = z;
	};
	swap(a, b);
	cout << a << " " << b << endl;
	int c = 30;
	int d = 40;
	//auto swap2 = [c, d]()//捕捉到c和d,当不加mutable的时候没法对c和d进行操作
	//{
	//	int z = c;
	//	c = d;
	//	d = z;
	//};
	//auto swap2 = [c, d]()mutable//可以对c和d进行操作,但是没有引用的话还是改变不了c和d的值
	//{
	//	int z = c;
	//	c = d;
	//	d = z;
	//};
	auto swap2 = [&c, &d]()//捕捉到c和d,对引用进行操作,可以改变c和d的值,同时可以不加mutable因为是对引用进行操作
	{
		int z = c;
		c = d;
		d = z;
	};
	swap2();
	cout << c << " " << d << endl;

注意,如果lambda表达式在全局中,就算有上文数据的话,捕捉列表也必须为空。

3.lambda的底层原理

用一段最简单的代码为例:

	auto func = [] {cout << "hello lambda" << endl; };//没有参数
	func();
	cout << typeid(func).name() << endl;

可以使用typeid类的name方法来查看一下lambda表达式的类型:
在这里插入图片描述
我们发现它的类型是一个类,其中<>中的长字符串是一个uuid,它是给编译器使用的,而不是给程序员使用的,经过一定的算法保证所有生成的uuid是不同的。
同时我们可以看一下汇编程序:
在这里插入图片描述
可以看到,调用lambda表达式其实就是调用该类的operator[]仿函数。

posted @ 2022-09-24 20:28  卖寂寞的小男孩  阅读(94)  评论(0)    收藏  举报