C++11:列表初始化、声明、STL升级
1、列表初始化
1.1 C++98传统的{}
在C++98中,标准允许使用花括号{}对数组或结构体元素进行统一的列表初始化
structPoint{int_x;int_y;};intmain(){intarray1[]={1,2,3,4,5};intarray2[5]={0};Point p={1,2};return0;}1.2 C++11中的{}
C++扩大了用大括号括起的列表(初始化列表)的使用范围,试图实现⼀切对象皆可用{}初始化,{}初始化的过程中,可以省略掉=,但建议不去掉=
intmain(){intarray1[]={1,2,3,4,5};intarray2[5]={0};Point p={1,2};// C++11中列表初始化应用在内置类型上intx1=1;intx2={1};intx3{1};return0;}创建对象时也可以使用列表初始化的方式来调用构造函数初始化
classDate{public:Date(intyear=1,intmonth=1,intday=1):_year(year),_month(month),_day(day){cout<<"Date(int year, int month, int day)"<<endl;}Date(constDate&d):_year(d._year),_month(d._month),_day(d._day){cout<<"Date(const Date& d)"<<endl;}private:int_year;int_month;int_day;};intmain(){Dated1(2025,9,18);Date d2={2025,9,18};Date d3{2025,9,18};// 可以省略赋值符号constDate&d4={2024,7,25};// 需要注意的是C++98支持单参数时类型转换,也可以不用{}Date d5={2025};Date d6=2025;return0;}2、C++11中的std::initializer_list
模拟实现vector中的{}初始化演示效果
template<classT>classvector{public:typedefT*iterator;vector(initializer_list<T>l){for(autoe: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应用演示
intmain(){vector<int>v1={1,2,3,4,5,6,7,8,8};// 任意多个int值的{}列表v1={1,2,3};autoil={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原来的用法,讲其用于实现自动类型判断。这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型
intmain(){inti=10;autop=&i;autopf=strcpy;cout<<typeid(p).name()<<endl;cout<<typeid(pf).name()<<endl;map<string,string>dict={{"sort","排序"},{"insert","插入"}};//map<string, string>::iterator it = dict.begin();autoit=dict.begin();return0;}输出结果:
int *
char * (__cdecl*)(char *,char const *)
3.2 不能使用auto的场景
- auto不能作函数形参
voidfunc(autox){}- auto不能作为函数的返回值
// C++11 报错,不能直接 auto 作返回值autotest(){return10;}- 数组类型推导不能直接 auto 数组
intarr[5]={1,2,3};autoa=arr;// a 是 int*,不是数组,丢失数组长度信息// 无法用 auto 保留原生数组类型,必须用 auto&auto&a2=arr;// 才是 int(&)[5]- new 分配时不能用 auto 单独写
autop=newauto(10);4、STL中的变化
下图1圈起来的就是STL中的新容器,但是实际最有用的是unordered_map和unordered_set。这两个我们前面已经进行了非常详细的讲解,其他的大家了解⼀下即可。
STL中容器的新接口也不少,最重要的就是右值引⽤和移动语义相关的push/insert/emplace系列
接口和移动构造和移动赋值,还有initializer_list版本的构造等,这些前面都讲过了,还有一些无关痛痒的如cbegin/cend等需要时查查文档即可。