C++11第一弹:简介 | 统一的列表初始化 | 声明

2024-09-05 13:33:37 浏览数 (2)

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增加的语法特性非常篇幅非常多,我们这里没办法一一讲解,所以本节课程主要讲解实际中比较实用的语法。

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 11文档

统一的列表初始化

{}初始化

{}初始化:一切皆可列表初始化。

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

代码语言:javascript复制
struct Point
{
	int _x;
	int _y;
};

int main()
{
	// C 
	int array1[] = { 1, 2, 3, 4, 5 };
	int array2[5] = { 0 };
	Point p = { 1, 2 };
	return 0;
}

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

代码语言:javascript复制
class A
{
public:
	A(int x,int y)
		:_x(x)
		,_y(y)
	{}

	A(int x)
		:_x(x)
		,_y(x)
	{}

private:
	int _x;
	int _y;
};

int main()
{
	int array1[] = { 1, 2, 3, 4, 5 };
	int array2[5] = { 0 };
	int array[5]{ 0 };

	//多参数的隐式类型转换
	A a1 = { 2,2 };
	A a5{ 2,2 };
	//单参数的隐式类型转换
	A a2 = 1;
	A a3 = { 1 };
	//隐式类型转换
	const A& a4 = { 2,2 };

	return 0;
}

std::initializer_list

std::initializer_list的介绍文档

std::initializer_list的类型:

内部有两个指针,一个指向开始,一个指向结束:

x自定义类型 = Y类型 -> 隐式类型转换 X(Y mm),X支持Y为参数类型构造就可以

代码语言:javascript复制
//vector(<initializer_list<T>> il);
vector<int> v5({ 1,2,3,4,5 });
代码语言:javascript复制
int main()
{
	vector<int> v1;
	vector<int> v2(10, 1);

	vector<int> v3 = { 1,2,3,4,5 };
	vector<int> v4 = { 10,20,30 };

	auto il1 = { 10,20,30 };
	initializer_list<int> il2 = { 10,20,30 };
	cout << typeid(il1).name() << endl;
	cout << typeid(il2).name() << endl;
	cout << sizeof(il1) << endl;
	//构造
	vector<int> v5({ 1,2,3,4,5 });
	//1.pair多参数的隐式类型转换  2.initializer_list<pair>的构造
	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };

	return 0;
}

声明

auto

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

x是对i的单纯的拷贝,x 不会影响i

默认auto推导的都是类型,但是使用引用,auto&时,xi的别名:

ji 的引用,任何对 j 的操作都会直接影响 iauto 推断 y 的类型为 int,因为 jint&(引用),yj 的副本,即 i 的副本。y 的值与 i 相同:

decltype

typeid可以查看数据类型,单纯的推出一个字符串,表示类型,但是不用用于定义对象:

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

decltype一般是配合模板传参使用:

代码语言:javascript复制
template<class T>
class B
{
public:
	T* New(int n)
	{
		return new T[n];
	}
};

auto func1()
{
	list<int> lt;
	auto ret = lt.begin();
	return ret;
}

int main()
{
	auto ret3 = func1();
	B<decltype(ret3)> bb1;

	return 0;
}

nullptr

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

代码语言:javascript复制
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

STL的变化

新容器

用橘色圈起来是C 11中的一些几个新容器,但是实际最有用的是unordered_mapunordered_set

容器中的一些新方法

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

0 人点赞