一致性初始化
引入原因
在没有引入之前,变量的初始化有许多方式 (如小括号,大括号,赋值号),且不同变量和类又有不同的初始化方式。(如,结构体能用{}初始化,类用{}则会出错。)
int i=1;
int i(1);
int i = int(1);
testStruct struct={"test",10};
testClass class=("test",10);
这样就很繁琐,所以引入一致性初始化,也就是说面对的初始化动作,都可以使用相同的语法来操作。也就是使用大括号。
int value[ ] {1,2,3,4};
std::vector<int> v {1,2,3,4,5};
int i {1}
注意1:窄化
然而对于窄化(也就是精度降低或者造成数值变动),对于大括号是不成立的。
也就是说,大括号可以由double转换成int而无法由int转换为double。
int i=1.0; //正确
int i2(1.0);//正确
int i3{1.0};//错误
int i4={1.0}//错误
初值列
众所周知,全局变量定义时候默认为0,局部变量定义时候,是没有值的即不确定的值,而引入初值列,会使局部变量得到初始值0/nullptr。
int i;//没有值
int j{};//初始化为0
int *p;//没有值
int *p{};//初始化为nullptr
用户自定义初值列
提供std::initializer_list<>来进行用户自定义类型之初值列操作。栗子:
#include<iostream>
#include<cstdio>
using namespace std;
void print(std::initializer_list<int> test)
{
for (auto *p=test.begin();p!=test.end();++p)
{
printf("%d\n",*p);
}
}
int main()
{
print({ 1,2,3,4,5,6 });
system("pause");
return 0;
}
用户自定义初值列也可以用来类的初始化
#include<iostream>
#include<cstdio>
using namespace std;
class MyClass
{
public:
MyClass() { printf("正常操作"); };
MyClass(std::initializer_list<int> t){ printf("传参错误"); }
~MyClass() {};
private:
};
int main()
{
MyClass test{123};
system("pause");
return 0;
}
当指明实参的构造函数和一个初值列的构造函数一起存在时,使用{}初始化时,初值列的构造函数优先调用。
class MyClass
{
public:
MyClass(int x) { printf("正常操作"); };
MyClass(std::initializer_list<int> t){ printf("传参错误"); }
~MyClass() {};
private:
};
int main()
{
MyClass test(123);//调用第一个构造函数
MyClass test1{123};//调用初值列构造函数
MyClass test2(123,789);//调用初值列构造函数
MyClass test3={123};//调用初值列构造函数
system("pause");
return 0;
}