初始值设定项列表与向量
Initializer list vs. vector
在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;
}
使用 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;
}
std::initializer_list
的常见用途是作为容器(和类似)类的构造函数的参数,允许从几个相同类型的对象方便地初始化这些容器。当然,您也可以以其他方式使用std::initializer_list
然后使用相同的{}
语法。
由于std::initializer_list
具有固定大小,因此不需要动态分配,因此可以有效地实现。另一方面,std::vector
需要动态内存分配。即使在您的简单示例中,编译器也不太可能优化此开销(避免中间std::vector
及其动态内存分配)。除此之外,程序的结果没有区别(尽管您应该采用const std::vector<int>&
参数以避免副本及其关联的动态内存分配)。
initializer_list
使用最佳存储位置并防止不必要的调用,它被设计为轻量级,而vector
有一个堆分配,可能会有更多的副本/移动。
两者的语义完全不同。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
您可以访问指向大括号 init-list 元素的const
指针,这意味着您别无选择,只能将这些元素复制到列表中。
如果需要,您可以sumV
从vector
中std::moved
元素(假设参数类型不是const
)。
同样,复制initializer_list
执行浅层复制,即只复制指针,而复制vector
当然意味着将复制元素。
在您的示例中,上述几点都没有真正产生任何区别,除了构造vector
需要动态内存分配,而构造initializer_list
则不需要。
initalizer_list不是像std::vector那样的通用容器。 它的主要目的是对象初始化。 如果低听和没有堆分配对你有吸引力,我建议看看 std::array。 它是一个固定大小的堆栈分配数组,具有 STL 容器的所有便利性,STL 容器本质上是 c 阵列之上的薄包装器。
初始值设定项列表
使用"支撑列表"语法创建的轻量级类似数组的元素容器。例如,{ 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 listn";
}
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
}
};
- 访问列表向量中的结构
- 从列表向量中删除无法按预期工作
- 从列表/向量制作嵌套 for 循环的最佳方法是什么?
- 在 c++ 中访问列表向量时出现问题
- 指向列表向量中的第n个元素
- 当迭代器添加到添加到列表向量的结构时,迭代器停止指向值?
- 如何将 for 循环中的每个迭代都放入列表/向量中?(C++)
- 删除列表向量中的元素并显示当前列表
- 如何与可以在列表/向量中使用的成员进行类型的类型
- 通过列表向量循环
- 如何使用C 创建多列列表/向量
- 存储动态创建对象的列表/向量的最佳方法是什么
- 基本STL:向量列表或列表向量,在这种特殊情况下哪个会更好
- Seg 错误初始化列表向量与控制台输入
- C++ 将文件读入数组/列表/向量
- 初始值设定项列表向量构造函数
- 如何在C++中初始化列表向量
- C++:保持实体列表向量与集合的最佳方式
- 如何将节点添加到列表向量
- 初始化列表向量时出错