初始化列表与向量

时间:2015-01-03 09:30:59

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

在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;
}

4 个答案:

答案 0 :(得分:9)

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

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

答案 1 :(得分:4)

两者的语义完全不同。 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内您可以访问指向 braced-init-list 元素的const指针,这意味着您没有其他选项可以复制列表中的元素。

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

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

在您的示例中,上述任何一点都没有任何区别,除了构建vector需要动态内存分配,而构建initializer_list则不会。

答案 2 :(得分:3)

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

答案 3 :(得分:2)

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