46

initializer_list对于未知数量的参数,的实际好处和目的是什么?为什么不直接使用vector并完成它呢?

事实上,它听起来只是一个vector有另一个名字的。何苦?

我看到的唯一“好处”initializer_list是它具有const元素,但这似乎不足以成为发明这种全新类型的理由。const vector(毕竟你可以只使用 a 。)

那么,我错过了什么?

4

3 回答 3

48

它是程序员和编译器之间的一种契约。程序员说{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}作为参数传递给g()如上所示,因为编译器无法直接创建out std::vectorof the expression的实例。这是因为程序员和编译器之间从来没有签订过这样的合同,并且是由语言强加的。正是通过,才能创造出自己的表达。{1,2,3,4} std::initializer_liststd::vector{1,2,3,4}

现在您将了解,std::initializer_list可以在需要 . 形式的表达式的任何地方使用{value1, value2, ...., valueN}。这就是为什么标准库中的其他容器也定义了std::initializer_list作为参数的构造函数。通过这种方式,没有容器依赖于任何其他容器来构造 形式的表达式{value1, value2, ...., valueN}

希望有帮助。

于 2013-01-19T13:36:39.390 回答
19

好吧,std::vector 必须使用initializer_list来获取该语法,因为它显然不能使用自己。

无论如何,initializer_list旨在极其轻量级。它可以使用最佳存储位置并防止不必要的复制。使用vector,您总是会获得堆分配,并且很有可能获得比您想要的更多的副本/移动。

此外,语法有明显的差异。其中之一是模板类型推导:

struct foo {
    template<typename T>  
    foo(std::initializer_list<T>) {}
};

foo x{1,2,3}; // works

vector不会在这里工作。

于 2013-01-19T13:30:43.013 回答
12

initializer_listover的最大优点vector是它允许您就地指定特定的元素序列,而无需专门的处理来创建该列表。

即使您确切知道哪些元素将被推入向量中,这也使您免于设置多个调用push_back(或for循环)来初始化 a 。vector

事实上,vector它本身有一个构造函数接受一个initializer_list更方便的初始化。我想说这两个容器是互补的。

// v is constructed by passing an initializer_list in input
std::vector<std::string> v = {"hello", "cruel", "world"};

当然,重要的是要意识到它initializer_list确实有一些限制(不允许缩小转换),这可能使其在某些情况下不合适或无法使用。

于 2013-01-19T13:40:12.527 回答