列表初始化
一、统一的初始化
#include <iostream>
using namespace std;class Test
{
public:Test(int) {}
private:Test(const Test &);
};// 数组的初始化
int array[] = { 1,3,5,7,9 };
double array1[3] = { 1.2, 1.3, 1.4 };// 对象的初始化
struct Person
{int id;double salary;
}zhang4{ 1, 4000 };int main(void)
{Test t1(520);Test t2 = 520; Test t3 = { 520 };Test t4{ 520 };int a1 = { 1314 };int a2{ 1314 };int arr1[] = { 1, 2, 3 };int arr2[]{ 1, 2, 3 };return 0;
}
- t1 通过有参构造实现了初始化
- t2 语法错误,提供的拷贝构造是私有的。如果拷贝构造函数是公共的,520会通过隐式类型转换被 Test(int)构造成一个匿名对象,然后再通过这个匿名对象进行拷贝构造得到t2
- t3 t4 使用了初始化列表的方式 效果与t1相同
t4、a2、arr2的写法,是C++11中新添加的语法格式,使用这种方式可以直接在变量名后边跟上初始化列表,来进行变量或者对象的初始化。
二、列表初始化细节
1.聚合体
- 普通数组本身可以看做是一个聚合类型
int x[] = {1,2,3,4,5,6}; double y[3][3] = { {1.1,2.2,3.3}, {4.4,5.5,6.6}, {7.7,8.8,9.9}}; char array[] = {'a','b','c','d','e'}; std::string sarry[] = {"hello","world","nihao","shijie"};
- class struct union 可以被看做一个聚合类型
- 无用户自定义的构造函数
- 无私有或保护的非静态数据成员(如果存在以上几种情况,就无法使用初始化列表)
#include <iostream>
using namespace std;struct T1
{int x;long y;
protected:int z;
}t{1,100,2}; //error ,类中有保护的成员,无法使用初始化列表初始化struct T2
{int x;long y;
protected:static int z;
}k{1,100,2}; //error 类中有静态成员可以使用初始化列表 ,但初始化列表不能初始化静态成员变量int main(){return 0;
}
- 无基类
- 无虚函数
2.非聚合体
- 对于聚合类型的类可以直接使用列表初始化进行对象的初始化
- 非聚合体也可以使用列表初始化,需要在类的内部自定义一个构造函数,在构造函数中使用初始化列表对类成员变量进行初始化。
例如:
#include <iostream>
#include <string>
using namespace std;struct Student
{int x;double y;//在构造函数中使用初始化列表初始化类成员Student(int a, double b,int c):x(a),y(b),z(c){}virtual void print(){cout << "x=" << x << " y=" << y << " z=" << z << endl;}private:int z;
};int main(){Student s1{10, 20.5, 30};s1.print();return 0;
}
- 聚合类型的定义并非递归----简单说 一个类的非静态成员是一个非聚合类型时,这个类也可能是聚合类型。
例如:
#include <iostream>
#include <string>
using namespace std;struct Student
{int x;double y;//在构造函数中使用初始化列表初始化类成员Student(int a, double b,int c):x(a),y(b),z(c){}Student(){}virtual void print(){cout << "x=" << x << " y=" << y << " z=" << z << endl;}private:int z;
};struct Classroom
{Student s;long x1;double y1;
};
int main(void){Student s1{10, 20.5, 30};s1.print();Classroom c1{{},520,3.14}; //使用{} 对非聚合类进行初始化 ,相当于调用Student的无参构造函数return 0;
}
三、std::initializer_list
使用
初始化列表只能进行固定函数的初始化,如果想要进行任意长度的初始化 可以使用 initializer_list(轻量级的模版类)
特点:
- 它是一个轻量级的容器类型,内部定义了迭代器 iterator等容器必须的概念,遍历时得到的迭代器是只读的。
- std::initializer_list<T> 它可以接收任意长度的初始化列表,但是要求元素必须是同种类型T
在std::initializer_list内部有三个成员接口:size(), begin(), end()
在std::initializer_list 只能被整体初始化或者赋值
1.作为普通函数参数
#include <iostream>
#include <string>
using namespace std;struct Student
{int x;double y;//在构造函数中使用初始化列表初始化类成员Student(int a, double b,int c):x(a),y(b),z(c){}Student(){}virtual void print(){cout << "x=" << x << " y=" << y << " z=" << z << endl;}private:int z;
};struct Classroom
{Student s;long x1;double y1;
};void func(initializer_list<int> ll)
{auto it = ll.begin();for(;it!=ll.end();++it){cout << *it << " ";}cout << endl;
}
int main(void){Student s1{10, 20.5, 30};s1.print();Classroom c1{{},520,3.14};func({1,2,3,4,5,7,8,9,666});return 0;
}
2.作为构造函数参数
#include <iostream>
#include <string>
#include <vector>
using namespace std;class Test {
public:Test(std::initializer_list<string> list){for (auto it = list.begin(); it != list.end(); ++it){cout << *it << " ";m_names.push_back(*it);}}private:std::vector<string> m_names;
};int main() {Test t({"hello", "world", "c++"});return 0;
}