【问题标题】:Optimization: Can I avoid a dynamic allocation of a vector in this loop?优化:我可以避免在这个循环中动态分配向量吗?
【发布时间】:2021-03-26 03:02:27
【问题描述】:

我想了解是否可以在以下代码中避免动态分配向量:

#include <vector>
int main() {
    std::vector<int> vec;
    while (predictate()) {
        int curr_size = foo();
        vec.resize(curr_size);
        bar(vec);
    }
};

perf 表明循环内大约 30% 的时间用于函数 vec.resize(curr_size)。是否可以在不过多更改程序中涉及的函数的 API 的情况下消除调整向量大小所花费的时间?我可以想到以下方法:

  • 使用std::array 而不是std::vector,因为我相信它可以避免动态重新分配。
  • vec 大小的上限是已知的。因此,我可以只分配一次内存并使用curr_size 作为bar 内的端点。
  • 我想知道std::vector 是否允许重置向量结束指针,但我找不到这样做的方法。这可能吗?

可以采取哪些步骤来避免花时间调整矢量大小?我没有这种优化的经验,很高兴听到更多有根据的建议。我很感激任何提示或建议!

【问题讨论】:

  • 查看std::vector::reserve(),在循环之前使用。
  • 你能显示真实的代码吗? resize 不应该那么贵,如果你 reserve 足够的前面
  • resize 从不缩小向量的容量。这意味着“浪费的时间”实际上应该只花在增长向量上的时间,如果你不知道最终的大小是多少,你就必须这样做。

标签: c++ optimization memory


【解决方案1】:

重新分配的成本很高。如果您预先预留足够的空间,则可以避免在循环内发生任何重新分配:

#include <vector>
int main() {
    std::vector<int> vec;

    vec.reserve( max_size );   // reserve enough space

    while (predictate()) {
        int curr_size = foo();
        vec.resize(curr_size);   // no rellocations when curr_size <= max_size
        bar(vec);
    }
};

如果您可以更改 bar 以采用迭代器,则无需调整大小(仍然假设您知道 foo() 的最大值):

    std::vector<int> vec( max_size );
    while (predictate()) {
        int curr_range = foo();
        bar(vec.begin(), vec.begin() + curr_range);
    }

【讨论】:

  • 非常感谢您的回复——这对我很有帮助! cpprefence 上的function description 上是否有任何信息表明当curr_size max_size 时不会发生重新分配。我一直在尝试阅读文档,但无法推断出这一点。
  • @fabian 我记得它没有明确提及,但由于其他要求而隐含。当我找到它时,我会在答案中添加更多内容
  • @fabian resize() page 说:“复杂性:当前大小和计数之间的差异呈线性关系。如果容量小于计数,重新分配可能会增加复杂性.”还可以阅读main vector page,其中包含有关重新分配的更多信息。
  • @fabian 它在注释中:“当调整到更小的尺寸时,向量容量永远不会减少,因为这会使所有迭代器失效,而不仅仅是那些将被等效的 pop_back() 序列失效的迭代器调用。”,尽管我必须搜索迭代器失效规则。当新的大小大于容量时,显然所有的迭代器都会失效。
猜你喜欢
  • 2020-05-27
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 2011-05-05
  • 1970-01-01
相关资源
最近更新 更多