为什么在参数中使用initializer_list而不是vector?

时间:2013-01-19 13:26:14

标签: c++

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

事实上,它听起来只是一个vector的另一个名字。为什么要这么麻烦?

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

那么,我在做什么?

3 个答案:

答案 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确实有一些限制(不允许缩小转换)这一事实,这可能会使某些情况下不适合或无法使用。