C++11新增特性:列表初始化(std::initializer_list)& decltype、auto、nullptr、范围for
一、C++11新增统一初始化方式
1.1 新增方式
在C++98之前,{}一般被用于对数组或结构体元素的统一的列表初始值设定。
struct Date
{
int year;
int monday;
int day;
};
int main()
{
int arr[5] = { 1, 2 ,3, 4, 5 };
Date d = { 2024, 4 ,14 };
return 0;
}
C++11扩大了初始化列表的使用范围,可用于所有的内置类型和自定义类型的初始化。并且在使用初始化列表时,等号可省略!!
struct Date
{
int year;
int monday;
int day;
};
int main()
{
int arr[5]{ 1, 2 ,3, 4, 5 };//省略等号
int i{ 1 };//初始化列表初始化内置类型,等价于int i = 1;或int i = {1};
Date d{ 2024, 4 ,14 };//省略等号
//C++中,初始化列表使用于new表达
//本质上是用花括号中的值生成一个initializer_list对象,在调用对于的构造函数
int* p = new int[5]{ 1, 2, 3 };
return 0;
}
在C++11中,初始化类列表可用于容器默认构造函数和拷贝复制函数的统一初始值设定!!
【部分容器使用示例】:
int main()
{
//构造函数的初始值设定
vector<int> v{ 1, 2, 3, 4, 5 };
list<int> l{ 1, 2, 3, 4, 5 };
map<string, string> m{
{"排序", "sort"},
{"快排", "qsort"},
{"水果", "fruits"}
};
//拷贝复制的初始值设定
vector<int> v1;
v1 = { 1, 3 ,5 ,7, 9 };
list<int> l1;
l1 = { 1 ,3 ,5, 7, 9 };
return 0;
}
1.2 初始化容器底层原理(std::initializer_list)
在C++11中,几乎所有的容器都新增了std::initializer_list
作为参数的构造函数和赋值重载函数,这样初始化容器对象就更方便了。
【以vector
为例】:
在执行vector<int> v{ 1, 2, 3, 4, 5 };
该种语句时,编译器会用花括号中的值1, 2, 3, 4, 5
构造出一个initializer_list对象。在通过调用容器中以initializer_list
作为参数的默认构造函数来生成对象v(拷贝赋值函数工作原理一样)
更具体的说,编译器会通过迭代器依次获取initializer_list
对象中的值,然后调用容器插入相关接口插入数据。
【下面以vector为例,实现过程】:
namespace Myvector
{
template<class T>
class vector
{
typedef T* iterator;
pubilc:
vector<T>(initializer_list<T> l)
{
_start = new T[l.size()];
_finish = _start + l.size();
_endofstorage = _finish;
iterator vit = _start;
typename initializer_list<T>::iterator lit = l.begin();
while (lit != l.end())
{
*vit++ = *lit++;
}
};
vector<T>& operator=(initializer_list<T> l)
{
vector<T> tmp(l);
std::swap(_start, tmp._start);
std::swap(_finish, tmp._finish);
std::swap(_endofstorage, tmp._endofstorage);
return *this;
}
priceate:
iterator _start = nullptr;
iterator _finish = nullptr;
iterator _endofstorage = nullptr;
};
}
二、新增声明
2.1 decltype
在C++中,我们可以通过typeid().name()
获取变量类型。但获取到的变量类型是以字符串形式显示的,无法作为类型定义变量继续使用。
在C++11中,新增关键字decltype
。decltype
可以将变量类型声明为表达式的指定类型!!
int main()
{
int x = 2;
double d = 4.2;
cout << typeid(x).name() << " " << typeid(d).name() << endl;
//error typeid(x).name()获取到的信息是一个字符串
//typeid(x).name() ret;
decltype(x * d) ret;//将ret声明为dobule
cout << typeid(ret).name() << endl;
return 0;
}
【运行结果】:
2.3 auto & nullptr & 范围for
有关C++11新增关键字和相关用法参考:CPP弥补了C的哪些缺陷及C++11新增特性