【问题标题】:Initializer list vs. vector初始化列表与向量
【发布时间】:2015-01-03 09:30:58
【问题描述】:

在 C++11 中,可以使用初始化列表来初始化函数中的参数。它的目的是什么?不能用 const 向量做同样的事情吗?下面这两个程序有什么区别?

使用初始化列表:

#include <iostream>

using namespace std;

int sumL(initializer_list<int> l){
    int sum = 0;
    for (const auto i: l){
        sum += i;
    }
    return sum;
}

int main(){

    cout << sumL({1, 2, 3}) << "\n";

    return 0;
}

使用 const 向量:

#include <iostream>
#include <vector>

using namespace std;

int sumV(const vector<int> l){
    int sum = 0;
    for (const auto i: l){
        sum += i;
    }
    return sum;
}

int main(){

    cout << sumV({1, 2, 3}) << "\n";
    return 0;
}

【问题讨论】:

  • 第二个代码需要的比需要的多(向量也是用 initializer_list 构造的)
  • Offtopic:请注意,您制作了向量的副本,即,您没有使用引用 &。在 for 循环中也是如此,现在它只是一个 int 但对于较大的对象,引用将避免复制向量中的每个对象。

标签: c++ c++11 vector initialization initializer-list


【解决方案1】:

std::initializer_list 的常见用途是作为容器(和类似)类的构造函数的参数,允许从几个相同类型的对象方便地初始化这些容器。 当然,你也可以使用 std::initializer_list 否则,然后使用相同的 {} 语法。

由于std::initializer_list 具有固定大小,它不需要动态分配,因此可以有效地实现。另一方面,std::vector 需要动态内存分配。即使在您的简单示例中,编译器也不太可能优化此开销(避免中间 std::vector 及其动态内存分配)。除此之外,您的程序的结果没有区别(尽管您应该使用const std::vector&lt;int&gt;&amp; 参数来避免复制及其相关的动态内存分配)。

【讨论】:

    【解决方案2】:

    initializer_list 使用最佳存储位置并防止不必要的调用,它被设计为轻量级,而 vector 有一个堆分配,可能会进行更多的复制/移动。

    【讨论】:

      【解决方案3】:

      两者的语义完全不同。 initializer_list 具有指针语义,而 vector 具有值语义。

      在您的第一个示例中,编译器将生成类似于以下的代码:

      int const __temp_array[3] = {1, 2, 3};
      cout << sumL(std::initializer_list<int>(__temp_array, __temp_array + 3)) << "\n";
      

      这在 [dcl.init.list]/5 中有解释。如您所见,在sumL 中,您可以访问const 指向braced-init-list 元素的指针,这意味着您别无选择,只能将元素复制出列表。

      如果是sumV,如果需要,您可以使用std::moved 中的元素vector(假设参数类型不是const)。

      同样,复制initializer_list 执行浅拷贝,即只复制指针,而复制vector,当然意味着将复制元素。

      在您的示例中,除了构造 vector 将需要动态内存分配,而构造 initializer_list 不会之外,以上几点都没有真正的区别。

      【讨论】:

      • 感谢您提供详细信息。请为我澄清一件事。如果说initializer_list&lt;object&gt; il1 = {...}; 将对象存储在容器内(或某处,堆栈上?),然后其副本initializer_list&lt;object&gt; il2 = il1; 存储指向对象的链接,那么ils 的每个副本都将共享相同的对象,我说得对吗?
      【解决方案4】:

      initializer_list 不是像 std::vector 这样的通用容器。它的主要目的是对象初始化。如果无意中听到的低且没有堆分配对您有吸引力,我建议您查看 std::array。它是一个固定大小的堆栈分配数组,具有 STL 容器的所有便利性,它本质上是一个 c 数组顶部的薄包装器。

      【讨论】:

        猜你喜欢
        • 2018-02-03
        • 2014-08-24
        • 1970-01-01
        • 2016-08-19
        • 2011-05-18
        • 1970-01-01
        • 2021-07-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多