目录
前言
小故事
C++11优势
统一的列表初始化
1.{}初始化
2. std::initializer_list
声明
1.auto
2.decltype
3.nullptr
前言
小故事
C++11优势
C++11是继1998年的后更新的C++大版本;C++11对比C++98带来了数量可观的变化,增加了很多新特性。相比较而言C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。所以对C++11的学习是很重要的。
这里是C++11的具体内容C++11 - cppreference.com,有兴趣的可以看看;
统一的列表初始化
1.{}初始化
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;
}
struct Point
{int _x;int _y;
};
int main()
{int x1 = 1;int x2{ 2 };int array1[]{ 1, 2, 3, 4, 5 };int array2[5]{ 0 };Point p{ 1, 2 };// C++11中列表初始化也可以适用于new表达式中int* pa = new int[4]{ 0 };return 0;
}
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;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2022, 1, 1); // old style// C++11支持的列表初始化,这里会调用构造函数初始化Date d2{ 2022, 1, 2 };Date d3 = { 2022, 1, 3 };return 0;
}
C++支持一切即可列表初始化,并且可以省略赋值符号;
2. std::initializer_list
小问题:date d={2024,9,4};和vector<int>v={2024,7,25};的{}有什么区别?
这两个{}本质上是不一样的,date d的{}会调用它的构造函数初始化d,而date类中只有三个参数,所以{}中只能有3个数;但是vector就不一样了,vector的{}中的元素数量是可变化的,并不是固定的三个;同样其他的容器list等也是如此;因此传递的参数是一个数组来进行初始化;为了方便统一,所以就出现了initializer_list的数组容器来统一作为数组参数;
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>using namespace std;int main()
{auto it = { 1,2,3 };//it就是initializer_list的类型的cout << typeid(it).name() << endl; return 0;
}
我们会发现数组的类型就是initializer_list而且是个模版;因此我们可以把initializer_list看成是一个{}形式的数组容器;
然后还提供了迭代器操作;我们可以来验证一下;
我们从调试中可以看出的确是包含了两个指针,分别指向数组的头和尾,而且提供了迭代器操作;另外我创建了一个局部变量,我们都知道局部变量是创建在栈上的,通过对比数组的地址和局部变量的地址我们可以推断出initializer_list是在栈上开辟的数组;
{}和initializer_list的优势体现:
例子:
map <string, string >mp = { {"apple","苹果"},{"banana","香蕉"},{"sort","排序"} };
分析:这个mp初始化使用了{}和initializer_list的结合;{"apple","苹果"}等是调用了pair<string ,string>的构造函数,最外层就是initializer_list;整体来看就是个pair<string,string>类型的数组;这样的好处就是不需要多次的创造pair<string,string>的临时变量进行初始化,极大的方便了c++玩家;
声明
1.auto
auto 可以自动的推导变量的类型,一般用于替代代码较长的类型或范围for循环中;
需要注意的是auto 后不可以用于函数参数或者返回类型;
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;
}
2.decltype
// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}
int main()
{
const int x = 1;
double y = 2.2;
decltype(x * y) ret; // ret的类型是double
decltype(&x) p; // p的类型是int*
cout << typeid(ret).name() << endl;
cout << typeid(p).name() << endl;
F(1, 'a');
return 0;
}
decltype也可以推导出变量的类型,但是与typeid不同的是他可以作为类型本身来使用;而typeid只能以字符串的形式打印出来;相比之下decltype更加的灵活;
3.nullptr
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif