初始化列表
C++98之初始化列表
其实在初始化列表这个词并不陌生,早在C++98中就已经引入了。可以通过{}一对大括号对数组元素进行统一的初始值设定。
如:int a{2}; int arr[] = {1,5,2};
但是这种方式初始化仅仅支持内置类型,也就是说结构体类型,容器都是不支持的。
例如下面这段代码,可以看到只有数组a能被正常初始化。
C++11之初始化列表
在C++11标准中,又对初始化列表的功能进行一次强化。
初始化列表前有无=等号作用相同,例如下面几种写法都是正确的。
1 int a = {5 + 5};
2 int a{2+1};
3 int a{3+1};
4 int* p = new int(1);
5 int* p = new int{9};
initializer_list模板类
用于对象的初始化
initializer_list
是C++11提供的新类型,定义在头文件中。用于表示某种特定类型的值的数组,和vector
一样,initializer_list是一种模板类型。
#include <iostream> #include <vector> #include <initializer_list> using namespace std; class A { public: A(int a, int b){} }; enum class Gender { boy = 1, girl = 2, }; class People { public: People(initializer_list<pair<string, Gender>> l) { initializer_list<pair<string, Gender>>::const_iterator iter = l.begin(); for(; iter != l.end(); ++iter) { data.push_back(*iter); } } private: vector<pair<string, Gender>> data; }; int main() { People pp = { {"aa", Gender::boy}, {"bb", Gender::girl} }; return 0; }
在上面的代码中,为这个类提供了一个initializer_list<pair<string, Gender>>模板版本的构造函数。这样就可以采用通过初始化列表的方式进行初始化了。
用于函数参数的初始化
initializer_list
除了可以初始化还可以作为函数的参数列表,就可以让函数支持初始化列表。
#include <iostream> #include <vector> #include <initializer_list> using namespace std; void test(initializer_list<int> iv){} int main() { test({ 1,5,3,99 }); test({ 1 }); return 0; }
在上面这个例子中,定义了一个接受初始化列表的函数test
。这种方法不局限于全局函数,成员函数也是可以的。
用于重载运算符
initializer_list还可以用在重载下标运算符中operator[]。
下面这个例子稍微复杂一点,但正因为复杂也能体现出初始化列表的便捷性。
创建了一个类A,其中重载了下标运算符,赋值运算符。实现了一个可以通过下标运算符[]来对数组内的值进行批量初始化。
1.重载下标运算符的目的是将需要初始化的下表进行一个记录,以便后续的初始化工作。
2.重载赋值运算符的目的是将之前记录的所有需要初始化的索引进行一个循环初始化工作。
#include <iostream> #include <vector> #include <initializer_list> using namespace std; class A { public: /* * 用于记录需要初始化的下表 */ A& operator[](initializer_list<int> l) { for(initializer_list<int>::const_iterator iter = l.begin(); iter != l.end(); ++iter) { index.push_back(*iter); } return *this; } /* * 用于将之前index提前保存好的下表进行统一初始化 */ A& operator=(int v) { if(false == index.empty()) { for (vector<int>::const_iterator iter = index.begin(); iter != index.end(); ++iter) { if (d.size() < *iter) { d.resize(*iter); } d.at(*iter - 1) = v; } index.clear(); return *this; } } void Print() { for(const auto elem : d) { cout << elem << " "; } cout << endl; } private: vector<int> index; // 辅助数组,用于记录index vector<int> d; }; int main() { A a; a[{1, 5, 8, 4}] = 1; a.Print(); a[{2, 1, 6, 9, 4}] = 6; a.Print(); return 0; }
可以看到我们自定义批量初始化仅需要一行即可完成a[{1, 5, 8, 4}] = 1;
。可见初始化的灵活性、强大性。