17

std::initializer_list由编译器从大括号括起来的初始化列表中构造,并且该列表的大小必须是编译时常量。

那么为什么委员会决定从模板参数中省略大小呢?这可能会阻止一些优化并使某些事情变得不可能(std::array从 a初始化std::initializer_list)。

4

2 回答 2

15

如果initializer_list定义为std::initializer_list<type, size>,那么任何采用 的函数initializer_list<type>(其中type是某种具体类型)现在都必须是基于该列表大小的模板函数。或者他们必须要求用户传递initializer_list一个特定类型和大小的。

这两个都是非常不可接受的。不是每个人都将他们所有的代码都写成模板。

您可以std::array从一个花括号初始化列表初始化 a ({}中间有东西)。但这与std::intiializer_list. 该类array是一个聚合类型。它是一个包含单个元素的结构,它是一个公共数组。因此,在符合 C++11 的实现上,它应该编译:

std::array<int, 3> myArray = {1, 3, 5};

然而,{1, 3, 5}不是一个std::initializer_list对象;它只是一个花括号初始化列表,可用于初始化适当的类型。

您不能将std::initializer_list对象传递给聚合的构造函数(因为聚合没有构造函数),但您可以使用花括号初始化列表来调用聚合初始化来初始化 a std::array,就像对任何包含数组的结构一样。

astd::initializer_list和 braced-init-list 之间的区别有点像 anint和 literal之间的区别0。将对象隐式转换为指针类型(通常)是不合法的int,但将整数文字 0 隐式转换为指针类型是合法的。支撑初始化列表的工作方式是这样的:

int i = 0;    //Legal
void *j = 0;  //Legal
void *k = i;  //Not legal

std::array<int, 3> myArray = {1, 3, 5};             //Legal
std::initializer_list<int> myInitList = {1, 3, 5};  //Legal
std::array<int, 3> myArray = myInitList;            //Not legal
于 2011-08-18T18:31:10.817 回答
8

One upside of the existing system is that you can export functions which take an initializer_list from a DLL. If it were templated on the size, they would have to be shipped as source.

于 2011-08-18T13:53:06.053 回答