【C++】C++11:列表初始化、声明、STL升级

C++11:列表初始化、声明、STL升级

1、列表初始化

1.1 C++98传统的{}

在C++98中,标准允许使用花括号{}对数组或结构体元素进行统一的列表初始化

cpp 复制代码
struct Point
{
	int _x;
	int _y;
};

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

	return 0;
}

1.2 C++11中的{}

C++扩大了用大括号括起的列表(初始化列表)的使用范围,试图实现⼀切对象皆可用{}初始化,{}初始化的过程中,可以省略掉=,但建议不去掉=

cpp 复制代码
int main()
{
	int array1[] = { 1, 2, 3, 4, 5 };
	int array2[5] = { 0 };
	Point p = { 1, 2 };

	// C++11中列表初始化应用在内置类型上
	int x1 = 1;
	int x2 = { 1 };
	int x3{ 1 };
	return 0;
}

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

cpp 复制代码
class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int year, int month, int day)" << endl;
	}

	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << "Date(const Date& d)" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2025, 9, 18);
	Date d2 = { 2025, 9, 18 };
	Date d3{ 2025, 9, 18 };   // 可以省略赋值符号
	const Date& d4 = { 2024, 7, 25 };
	
	// 需要注意的是C++98支持单参数时类型转换,也可以不用{}
	Date d5 = { 2025 };
	Date d6 = 2025;
	
	return 0;
}

2、C++11中的std::initializer_list

模拟实现vector中的{}初始化演示效果

cpp 复制代码
template<class T>
class vector {
public:
	typedef T* iterator;
	vector(initializer_list<T> l)
	{
		for (auto e : l)
			push_back(e)
	}
	
	// 赋值
	vector& operator= (initializer_list<T> il)
	{
		vector<T> tmp(il);
		
		swap(tmp);
		
		return *this;
	}
	
	map& operator= (initializer_list<value_type> il);
private:
	iterator _start = nullptr;
	iterator _finish = nullptr;
	iterator _endofstorage = nullptr;
};

std::initializer_list应用演示

cpp 复制代码
int main()
{
	vector<int> v1 = { 1,2,3,4,5,6,7,8,8}; // 任意多个int值的{}列表
	v1 = { 1,2,3 };
	
	auto il = { 1,2,3,4,5,6,7,8,8 };
	cout << sizeof(il) << endl;
	cout << typeid(il).name() << endl;
	
	// 这里是pair对象的{}初始化和map的initializer_list构造结合到一起用了
	map<string, string> dict = { {"sort", "排序"}, {"string", "字符串"} };
}

3、声明

C++11提供了多种简化声明的方式,尤其是在使用模板时

3.1 auto

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

cpp 复制代码
int main()
{
	int i = 10;
	auto p = &i;
	auto pf = strcpy;
	cout << typeid(p).name() << endl;
	cout << typeid(pf).name() << endl;
	map<string, string> dict = { {"sort", "排序"}, {"insert", "插入"} };
	//map<string, string>::iterator it = dict.begin();
	auto it = dict.begin();
	return 0;
}

输出结果:

int *

char * (__cdecl*)(char *,char const *)

3.2 不能使用auto的场景

  • auto不能作函数形参
cpp 复制代码
void func(auto x) {}
  • auto不能作为函数的返回值
cpp 复制代码
// C++11 报错,不能直接 auto 作返回值
auto test() {
    return 10;
}
  • 数组类型推导不能直接 auto 数组
cpp 复制代码
int arr[5] = {1,2,3};
auto a = arr; // a 是 int*,不是数组,丢失数组长度信息
// 无法用 auto 保留原生数组类型,必须用 auto&
auto& a2 = arr; // 才是 int(&)[5]
  • new 分配时不能用 auto 单独写
cpp 复制代码
auto p = new auto(10);

4、STL中的变化

下图1圈起来的就是STL中的新容器,但是实际最有用的是unordered_map和unordered_set。这两个我们前面已经进行了非常详细的讲解,其他的大家了解⼀下即可。

STL中容器的新接口也不少,最重要的就是右值引⽤和移动语义相关的push/insert/emplace系列

接口和移动构造和移动赋值,还有initializer_list版本的构造等,这些前面都讲过了,还有一些无关痛痒的如cbegin/cend等需要时查查文档即可。

相关推荐
ComputerInBook12 小时前
c 和 c++ 中的宏块(macro)
c语言·c++··宏块·宏指令
AA陈超13 小时前
004 T02 - 俯视角摄像机系统 设计文档
网络·c++·ue5·虚幻引擎
bu_shuo13 小时前
c与cpp中的argc和argv
c语言·c++·算法
蓝创精英团队13 小时前
VCPKG 跨平台C++ 库管理器
c++·vcpkg
Jayden_Ruan14 小时前
C++组合的输出
c++·算法·深度优先
froyoisle15 小时前
CSP 真题解析:[CSP-J 2020-T3] 表达式
c++·算法·csp·信息学·信奥赛
Darkwanderor15 小时前
动、静态库相关内容的详细介绍
linux·c语言·开发语言·c++
文祐15 小时前
C++类之虚函数表没有虚继承的菱形继承
开发语言·c++·算法
孬甭_17 小时前
C++ string类
开发语言·c++