c++ 初始化器列表与向量

t9aqgxwy  于 2023-03-14  发布在  其他
关注(0)|答案(5)|浏览(184)

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

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

使用常量向量:

#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;
}
bvpmtnay

bvpmtnay1#

std::initializer_list的常见用法是作为容器类(或类似的)构造函数的参数,允许从相同类型的几个对象方便地初始化这些容器。当然,您也可以使用std::initializer_list,然后使用相同的{}语法。
因为std::initializer_list有固定的大小,它不需要动态分配,因此可以有效地实现。另一方面,std::vector需要动态内存分配。即使在您的简单示例中,编译器也不太可能优化掉这个开销(避免中间体std::vector及其动态内存分配)。除此之外,程序的结果没有什么不同(尽管您应该使用const std::vector<int>&参数来避免复制及其相关的动态内存分配)。

brccelvz

brccelvz2#

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

kxxlusnw

kxxlusnw3#

两者的语义有很大的不同,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,如果需要,您可以将vector中的元素设置为std::moved(假设参数类型不是const)。
类似地,复制initializer_list执行浅复制,即,仅复制指针,而复制vector当然意味着将复制元素。
在您的示例中,除了构造vector需要动态内存分配而构造initializer_list不需要之外,以上各点实际上没有任何区别。

xmjla07d

xmjla07d4#

initalizer_list不是像std::vector那样的通用容器。它的主要用途是对象初始化。如果低的偶然性和没有堆分配对你有吸引力,我建议你看看std::array。它是一个固定大小的堆栈分配数组,具有STL容器的所有便利,它本质上是一个在c数组顶部的薄 Package 器。

n8ghc7c1

n8ghc7c15#

初始化程序列表

使用“花括号列表”语法创建的元素的轻量级类似数组的容器。例如,{ 1,2,3 }创建一个整数序列,其类型为std::initializer_list。用作将对象向量传递给函数的替代。

int sum(const std::initializer_list<int>& list) {
  int total = 0;
  for (auto& e : list) {
    total += e;
  }

  return total;
}

auto list = {1, 2, 3};
sum(list); // == 6
sum({1, 2, 3}); // == 6
sum({}); // == 0

然而,在您的情况下,如果您将以您正在进行的编译器的方式进行优化,则可能以与您可以看到下面提到的向量函数实现相同的方式进行优化。

template <class T>
struct S {
    std::vector<T> v;
    S(std::initializer_list<T> l) : v(l) {
         std::cout << "constructed with a " << l.size() << "-element list\n";
    }
    void append(std::initializer_list<T> l) {
        v.insert(v.end(), l.begin(), l.end());
    }
    std::pair<const T*, std::size_t> c_arr() const {
        return {&v[0], v.size()};  // copy list-initialization in return statement
                                   // this is NOT a use of std::initializer_list
    }
};

相关问题