C++11特性 - 基础部分

C++11 - 部分特性(基础)

本节内容包含列表初始化,initializer_list的使用,decltype,nullptr

1.列表初始化

C++98(包括C语言中)允许使用花括号对数组或者结构体元素进行列表初始值的设定

struct Point
{
	int x;
	int y;
};

int main()
{
	int arry[] = { 1, 2, 3, 4, 5 };

	Point p = { 0, 1 };
	
	return 0;
}

C++11扩大了括号括起的列表(初始化列表)的范围,使其可以省略等号

struct Point
{
	int x;
	int y;
};

int main()
{
	int arry[]{ 1, 2, 3, 4, 5 };

	Point p{ 0, 1 };
	// C++11的列表初始化也可以适用于new表达式中
	// 开一个数组,并初始化为1,2,3,4
	int* pa = new int[4]{ 1, 2, 3, 4 };	

	return 0;
}

结论:C++11支持的列表初始化对于自定义类型去使用都是调用对方的构造函数

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;
	}

	Date(const Date& d)
	{
		cout << "Date(const Date & d1)" << endl;

		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2022, 1, 1); // old style
	// C++11支持的列表初始化,这里调用的是Date构造
	Date d2{ 2022, 1, 2 };
	Date d3 = { 2022, 1, 3 };

	// 这里调用的是Date的拷贝构造
	Date d4(d3);
	
	return 0;
}

2.initializer_list的使用

在这里插入图片描述

C++11中多数容器都内置了initializer_list,其作用是支持{ }给容器赋值

vector<int> v为例,如果没有initializer_list,赋值的时候则需要v.push_back(val)的方式不断向内部插入值,但是内置了initializer_list,就可以直接用vector<int> v = {1, 2, 3, 4};的方式赋值,这样就可以支持STL的容器进行大括号赋值

std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。也可以作为operator=的参数,这样就可以用大括号赋值。

结论:initializer_list的出现方便了STL容器的初始化

struct Point
{
public:
	Point(int x, int y)
		:_x(x)
		,_y(y)
	{
		cout << "Point(int x, int y) -- 构造" << endl;
	}

	Point(const Point& p)
	{
		_x = p._x;
		_y = p._y;

		cout << "Point(const Point& p) -- 拷贝构造" << endl;
	}

	Point& operator=(const Point& p)
	{
		if (this != &p)
		{
			_x = p._x;
			_y = p._y;
		}

		cout << "Point& operator=(const Point& p) -- 赋值" << endl;
	}

private:
	int _x;
	int _y;
};

int main()
{
	// 区分不同的规则
	vector<int> v = { 1, 2, 3, 4, 5 }; // 调用的是initializer_list的vector构造函数
	// 隐式类型转换 - 调用两次构造函数,首先构造{1, 1},在用他去构造p
	// 调用两次构造,编译器会优化成直接构造,所以结果是一次构造
	Point p = { 1, 2 };  // 编译器的优化

	return 0;
}

模拟实现的vector,内部集成initializer_list,遍历并push即可实现大括号赋值

vector(initializer_list<T> lt)
{
	reserve(lt.size());
	for (auto e : lt)
	{
		push_back(e);
	}
}

3.decltype

decltypetypeid的区别:typeid仅能查看变量的类型,不能作为类型再去定义变量,decltype推出对象的类型,再定义变量,或者作为模板实参

int main()
{
	auto a = 10;

	cout << typeid(a).name() << endl;
	
	// decltype推出对象的类型,再定义变量,或者作为模板实参
	decltype(a) b; 
	vector<decltype(a)> v1;

	const int x = 1;
	double y = 2.2;

	cout << typeid(x * y).name() << endl;
	vector<decltype(x * y)> v2;

	return 0;
}

4.nullptr

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

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

END!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值