对于未知数量的参数,initializer_list
的实际好处和目的是什么?为什么不使用vector
并完成它?
事实上,它听起来只是一个vector
的另一个名字。为什么要这么麻烦?
我看到initializer_list
唯一的“好处”是它有const
个元素,但这似乎不足以发明这个全新的类型。 (毕竟你可以使用const vector
。)
那么,我在做什么?
答案 0 :(得分:33)
这是程序员和编译器之间的一种契约。程序员说{1,2,3,4}
,编译器从中创建一个类型为initializer_list<int>
的对象,其中包含相同的元素序列。此契约是语言规范对编译器实现强加的要求。
这意味着,不是程序员手动创建这样的对象,而是编译器创建对象,并将该对象传递给以initializer_list<int>
为参数的函数。
std::vector
实现利用了这个契约,因此它定义了一个以initializer_list<T>
为参数的构造函数,以便它可以用初始化列表中的元素初始化自己。
现在假设有一段时间 std::vector
没有任何以std::initializer_list<T>
为参数的构造函数,那么你会得到这个:
void f(std::initializer_list<int> const &items);
void g(std::vector<int> const &items);
f({1,2,3,4}); //okay
g({1,2,3,4}); //error (as per the assumption)
根据假设,由于std::vector
没有以std::initializer_list<T>
作为参数的构造函数,暗示,因此无法将{1,2,3,4}
作为参数传递给{ {1}}如上所示,因为编译器无法直接从表达式g()
创建std::vector
的实例。这是因为程序员和编译器之间没有这样的契约,并且由语言强加。它是到 {1,2,3,4}
,std::initializer_list
能够在表达式std::vector
之外创建自己。
现在您将了解{1,2,3,4}
可以在任何需要std::initializer_list
形式的表达式的地方使用。这就是为什么Standard库中的其他容器也定义了以{value1, value2, ...., valueN}
作为参数的构造函数。通过这种方式,任何容器都不依赖于任何其他容器来构造std::initializer_list
。
希望有所帮助。
答案 1 :(得分:16)
好吧,std::vector
使用initializer_list
来获取该语法,因为它显然无法使用它。
无论如何,initializer_list
旨在非常轻量级。它可以使用最佳存储位置并防止不必要的副本。使用vector
,您总是可以获得堆分配,并且很有可能获得比您想要的更多的副本/移动。
此外,语法有明显的差异。其中一个是模板类型推导:
struct foo {
template<typename T>
foo(std::initializer_list<T>) {}
};
foo x{1,2,3}; // works
vector
在这里不起作用。
答案 2 :(得分:10)
initializer_list
优于vector
的最大优势在于,它允许您指定就地某个元素序列,而无需专门处理来创建该列表。
这样可以避免设置多次调用push_back
(或for
周期)以初始化vector
,即使您确切知道要将哪些元素推入向量中
实际上,vector
本身有一个构造函数接受initializer_list
以便更方便地进行初始化。我想说这两个容器是互补的。
// v is constructed by passing an initializer_list in input
std::vector<std::string> v = {"hello", "cruel", "world"};
当然,重要的是要注意initializer_list
确实有一些限制(不允许缩小转换)这一事实,这可能会使某些情况下不适合或无法使用。