C++中向量初始化的性能

Posted

技术标签:

【中文标题】C++中向量初始化的性能【英文标题】:Performance of vector initialization in C++ 【发布时间】:2014-05-28 19:48:35 【问题描述】:

假设你从另一个容器初始化一个向量:

main()

    list<int> L  0, 1, 2 ;
    vector<int> V ( L.begin(), L.end() );
    copy ( V.begin(), V.end(), ostream_iterator<int> ( cout, " " ) );
    cout << endl;

向量大小是设置一次,还是在初始化期间动态调整大小? (在此示例中不是问题,因为源中的元素很少,但如果源中的元素非常多,则可能会出现问题。)

【问题讨论】:

一次。如果您设法仅通过 L 一次(您的代码执行一次以计算大小并复制一次),则会获得奖励积分。 【参考方案1】:

您正在使用两个迭代器(和一个隐藏的分配器参数)调用std::vector 的模板化构造函数。这就是相关的标准报价所说的:

23.3.6.2 向量构造函数、复制和赋值[vector.cons]

template <class InputIterator> 
vector(InputIterator first, InputIterator last, const Allocator& = Allocator());

9 效果: 构造一个等于范围 [first,last) 的向量,使用 指定的分配器。

10 复杂性:仅对副本进行 N 次调用 T 的构造函数(其中 N 是第一个和最后一个之间的距离)和 如果迭代器 first 和 last 是向前的,则没有重新分配, 双向或随机访问类别。它使订单 N 调用 T 的复制构造函数和 order log(N) 重新分配,如果它们是 只需输入迭代器。

因为您是从std::list(双向迭代器)初始化的,所以只有一个分配。

从标准输入 OTOH 读取是使用输入迭代器完成的,然后可能会有多个重新分配。请注意,元素在内存中移动的平均次数仍然是O(1)(由于指数内存分配策略)。

【讨论】:

您的参考与我的不同。您是否有一份标准的草稿副本? 另一件事是,如果发生重新分配,那么最终的向量大小可能会比必要的大得多。 (我说的是很多元素。) @TemplateRex:学究们现在会开心多了! :-) @Brian 是的,我引用自 N3690 仍然有 dynarray,因此编号不同 @JohnH。是的,容量可以超过要求的容量,但您可以使用shrink_to_fit 【参考方案2】:

根据 §23.3.6.2/10 中的标准,只要迭代器是前向迭代器、双向迭代器或随机访问迭代器,就没有重新分配。如果迭代器是输入迭代器,则有 O(log N) 次重新分配。

注意:std::list 具有双向迭代器。

你问这是如何实现的?据推测,它会计算两个迭代器之间的距离(或调用std::distance 或内部版本),然后再进行一次实际初始化向量。

【讨论】:

以上是关于C++中向量初始化的性能的主要内容,如果未能解决你的问题,请参考以下文章

向量 .reserve() 和分配效率 (C++)

在 C++ 中初始化非常大的向量

运行时在构造函数中初始化向量类成员——C++

如何在 C++ 中初始化向量 [重复]

如何初始化 2D 向量 C++ [重复]

如何在 C++ 中使用构造函数初始化二维向量?