std::initializer_list
由编译器从大括号括起的init列表构造,此列表的大小必须是编译时常量。
那么为什么委员会决定从模板参数中省略大小?这可能会阻止一些优化并使某些事情变得不可能(从std::array
初始化std::initializer_list
)。
答案 0 :(得分:14)
如果initializer_list
被定义为std::initializer_list<type, size>
,则任何带有initializer_list<type>
的函数,其中type
是某种具体类型,现在必须是基于该列表大小的模板函数。或者他们必须要求用户传递特定类型和大小的initializer_list
。
这两个都是非常不可接受的。并非所有人都将所有代码都写为模板。
您可以从braced-init-list(std::array
初始化{}
,其中包含中间的内容。但这与std::intiializer_list
不同。 array
类是聚合类型。它是一个包含单个元素的结构,它是一个公共数组。因此,在符合C ++ 11的实现上,这应该编译:
std::array<int, 3> myArray = {1, 3, 5};
但是,{1, 3, 5}
不是std::initializer_list
对象;它只是一个braced-init-list,可以用来初始化合适的类型。
您无法将std::initializer_list
对象传递给aggegate的构造函数(因为聚合没有构造函数),但您可以使用braced-init-list调用聚合初始化来初始化std::array
,就像你对任何包含数组的结构一样。
std::initializer_list
和braced-init-list之间的差异有点像int
和文字0
之间的差异。将int
对象隐式转换为指针类型并不(通常)合法,但将整数文字0隐式转换为指针类型是合法的。 braced-init-lists的工作方式是这样的:
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
答案 1 :(得分:7)
现有系统的一个优点是您可以导出从DLL中获取initializer_list
的函数。如果按尺寸模板化,则必须将它们作为来源运输。