C++11新特性统一初始化
Posted 老虎中的小白Gentle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11新特性统一初始化相关的知识,希望对你有一定的参考价值。
为什么提出统一初始化?
在C++11之前,程序员,尤其是新手,很容易被如何初始化变量或对象的问题弄糊涂。初始化可以使用圆括号、大括号和赋值操作符(=)。因此,C++11引入了统一初始化的概念,这意味着对于任何初始化,你都可以使用一种通用语法。这个语法使用了大括号。
举一些统一初始化的例子
#include <iostream>
#include <vector>
#include <string>
#include <complex>
using namespace std;
int main()
{
int i{ 10 }; //等效于 int i = 10;
int values[]{ 1,2,3 };
vector<int> v{ 0,2,4,6,8 };
vector<string>cities{ "hello","please give a like","Gentle" };
complex<double> c{ 4.0, 3.0 }; // 等效于c(4.0,3.0)
return 0;
}
上面是用法,下面是深入其根本探究。
initializer_list<>
其实是利用一个事实:编译器看到{t1,t2…tn}便做出一个initializer_list,它关于一个array<T,n>。调用函数(例如构造函数)时,该array内的元素可被编译器分解逐一传给函数。但若函数参数是个initializer_list,调用者却不能给予数个T参数然后以为它们会被自动转为一个initializer_list传入。
vector<string>cities{ "hello","please give a like","Gentle" };
这形成一个initializer_list,背后有个array<string,3>。调用vector的构造函数时,编译器找到了一个vector的构造函数接受initializer_list。所以容器皆有如此的构造函数。
complex<double> c{ 4.0, 3.0 };
这形成一个initializer_list,背后有个array<double,2>。调用complex构造函数时array内的2个元素被分解传给构造函数。complex并无任何构造函数接受initializer_list。
为了支持用户定义类型的初始化列表的概念,C++11提供了类模板std::initializer_list<>。它可以用于支持按值列表或按你想要处理一列值的任何其他地方。例如:
#include <iostream>
using namespace std;
void print(std::initializer_list<int> vals)
{
for (auto p = vals.begin(); p != vals.end(); ++p) //一列参数,容器的操作
{
std::cout << *p << endl;
}
}
int main()
{
print({ 1,3,5,7,9 }); //传入一列参数给print
/*输出的结果如下
1
3
4
5
7
9
*/
return 0;
}
当构造函数用于指定参数数量和初始化列表时,具有初始化列表的版本是首选的
这句怎么理解呢?看例子:
#include <iostream>
using namespace std;
class P
{
public:
//part 1
P(int a, int b)
{
cout << "P(int, int), a=" << a << ", b=" << b << endl;
}
//part 2
P(initializer_list<int> initlist)
{
cout << "P(initializer_list<int>), values= ";
for (auto i : initlist)
cout << i << ' ';
cout << endl;
}
};
int main()
{
P p(77, 5); //P(int, int), a=77, b=5
P q{ 77,5 }; //P(initializer_list<int>), values = 77 5
P r{ 77,5,42 }; //P(initializer_list<int>), values = 77 5 42
P s = { 77,5 }; //P(initializer_list<int>), values = 77 5
return 0;
如果没有初始化列表的构造函数,将调用接受两个int值的构造函数来初始化q和s,而初始化r将无效。
initializer_list<>的原代码
初始化器列表
初始化器列表强制进行所谓的值初始化,这意味着即使是基本数据类型的局部变量(通常具有未定义的初始值)也被初始化为零(如果是指针,则为nullptr)。
int i; //未被初始化
int j{}; //初始化为0
int *p; //为被初始化
int *q{};//被初始化为nullptr
但是请注意,使用大括号是不可能缩小初始化的—减少精度或修改所提供的值
int x1(5.3); //可以这样,waring:从"double"转换到"int",可能丢失数据
int x2 = 5.3;//可以这样,waring:从"double"转换到"int",可能丢失数据
int x3{ 5.0 };//error:从"double"转换到"int"需要收缩转换
int x4 = { 5.3 };//error:从"double"转换到"int"需要收缩转换
char c1{ 7 }; //ok
char c2{ 9999 }; //error: 从"int"转换到"char"需要收缩转换
vector<int> v1{ 1,2,4,5 }; //ok
vector<int> v2{ 1,2.3,4,5.6 };//error:从"double"到"int"进行收缩转换无效```
以上是关于C++11新特性统一初始化的主要内容,如果未能解决你的问题,请参考以下文章