在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;
}
5条答案
按热度按时间bvpmtnay1#
std::initializer_list
的常见用法是作为容器类(或类似的)构造函数的参数,允许从相同类型的几个对象方便地初始化这些容器。当然,您也可以使用std::initializer_list
,然后使用相同的{}
语法。因为
std::initializer_list
有固定的大小,它不需要动态分配,因此可以有效地实现。另一方面,std::vector
需要动态内存分配。即使在您的简单示例中,编译器也不太可能优化掉这个开销(避免中间体std::vector
及其动态内存分配)。除此之外,程序的结果没有什么不同(尽管您应该使用const std::vector<int>&
参数来避免复制及其相关的动态内存分配)。brccelvz2#
initializer_list
使用最佳存储位置并防止不必要的调用,它被设计为轻量级的,而vector
有一个堆分配,可能会进行更多的复制/移动。kxxlusnw3#
两者的语义有很大的不同,
initializer_list
有指针语义,而vector
有值语义。在第一个示例中,编译器将生成类似于以下内容的代码:
sumL
中,您可以访问指向 braced-init-list 中元素的const
指针,这意味着您别无选择,只能将元素复制出列表。对于
sumV
,如果需要,您可以将vector
中的元素设置为std::moved
(假设参数类型不是const
)。类似地,复制
initializer_list
执行浅复制,即,仅复制指针,而复制vector
当然意味着将复制元素。在您的示例中,除了构造
vector
需要动态内存分配而构造initializer_list
不需要之外,以上各点实际上没有任何区别。xmjla07d4#
initalizer_list不是像std::vector那样的通用容器。它的主要用途是对象初始化。如果低的偶然性和没有堆分配对你有吸引力,我建议你看看std::array。它是一个固定大小的堆栈分配数组,具有STL容器的所有便利,它本质上是一个在c数组顶部的薄 Package 器。
n8ghc7c15#
初始化程序列表
使用“花括号列表”语法创建的元素的轻量级类似数组的容器。例如,{ 1,2,3 }创建一个整数序列,其类型为std::initializer_list。用作将对象向量传递给函数的替代。
然而,在您的情况下,如果您将以您正在进行的编译器的方式进行优化,则可能以与您可以看到下面提到的向量函数实现相同的方式进行优化。