多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
nitializer\_list是C++11提供的新类型,定义在头文件中。 用于表示某种特定类型的值的数组,和vector一样,initializer\_list也是一种模板类型。 ``` template< class T > class initializer_list; ``` ## 列表初始化 C++11扩大了初始化列表的适用范围,使其可用于所有内置类型和用户定义的类型。无论是初始化对象还是某些时候为对象赋新值,都可以使用这样一组由花括号括起来的初始值了。使用初始化列表时,可添加=,也可不添加。 ``` //定义一个变量并初始化 int units_sold=0; int units_sold(0); int units_sold={0}; //列表初始化 int units_sold{0}; //列表初始化 ``` 当初始化列表用于内置类型的变量时,这种初始化形式有一个重要特点:如果我们使用列表初始化值存在丢失信息的风险,则编译器将报错: ~~~ long double ld=3.1415926536; int a={ld},b={ld}; //错误:转换未执行,因为存在丢失信息的风险 int c(ld),d=ld; //正确:转换执行,且确实丢失了部分值 ~~~ ## initializer\_list的使用 它提供的操作如下: ~~~ initializer_list<T> lst; //默认初始化;T类型元素的空列表 initializer_list<T> lst{a,b,c...}; //lst的元素数量和初始值一样多;lst的元素是对应初始值的副本 lst2(lst) lst2=lst //拷贝或赋值一个initializer_list对象不会拷贝列表中的元素;拷贝后,原始列表和副本元素共享 lst.size() //列表中的元素数量 lst.begin() //返回指向lst中首元素的指针 lst.end() //返回指向lst中尾元素下一位置的指针 ~~~ 需要注意的是,initializer\_list对象中的元素永远是常量值,我们无法改变initializer\_list对象中元素的值。并且,拷贝或赋值一个initializer\_list对象不会拷贝列表中的元素,其实只是引用而已,原始列表和副本共享元素。 和使用vector一样,我们也可以使用迭代器访问initializer\_list里的元素 ~~~ void error_msg(initializer_list<string> il) { for(auto beg=il.begin();beg!=il.end();++beg) cout<<*beg<<" "; cout<<endl; } ~~~ 如果想向initializer\_list形参中传递一个值的序列,则必须把序列放在一对花括号内: ~~~ //expected和actual是string对象 if(expected != actual) error_msg({"functionX",expectde,actual}); else error_msg({"functionX","okay"}); ~~~ 说了这么多,那initializer\_list到底有什么应用呢? 有了initializer\_list之后,对于STL的container的初始化就方便多了,比如以前初始化一个vector需要这样: ~~~ std::vector v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); ~~~ 而现在c++11添加了initializer\_list后,我们可以这样初始化 ~~~ std::vector v = { 1, 2, 3, 4 }; ~~~ 并且,C++11允许构造函数和其他函数把初始化列表当做参数。 ~~~ #include <iostream> #include <vector> class MyNumber { public: MyNumber(const std::initializer_list<int> &v) { for (auto itm : v) { mVec.push_back(itm); } } void print() { for (auto itm : mVec) { std::cout << itm << " "; } } private: std::vector<int> mVec; }; int main() { MyNumber m = { 1, 2, 3, 4 }; m.print(); // 1 2 3 4 return 0; } ~~~