C++ STL:清关后的容器再利用或再利用

C++ STL: Container Recreation or Reuse after clearing?

本文关键字:再利用 STL C++      更新时间:2023-10-16

在编程中,我们面临着需要使用中间STL容器的各种情况,如以下示例所示:

while(true)
{
    set < int > tempSet;
    for (int i = 0; i < n; i ++)
    {
        if (m.size() == min && m.size() <= max)
        {
            tempSet.insert(i);
        }
    }
    //Some condition testing code
}

set < int > tempSet;
while(true)
{
    for (int i = 0; i < n; i ++)
    {
        if (m.size() == min && m.size() <= max)
        {
            tempSet.insert(i);
        }
    }
    tempSet.clear();
    //Some condition testing code
}

考虑到C++编译器的现状,在时间和空间复杂性方面,哪种方法更好?

第一个版本是正确的。 它几乎在各个方面都更简单。 更容易写,更容易阅读,更容易理解,更容易维护,等等。

第二个版本可能更快,但话又说回来,它可能不会。 在使用之前,您需要证明它具有显着的优势。 在大多数非平凡的情况下,我猜两者之间不会有可衡量的性能差异。

有时在嵌入式编程中,避免将东西放在堆栈上很有用;在这种情况下,第二个版本是正确的。

默认情况下使用第一个版本;仅当您可以给出这样做的充分理由时才使用第二个版本(如果原因是性能,那么您应该有证据表明好处是显着的)。

我说第一个更防错误。您不必记住清除它(它只会超出范围并完成)。:-)

在性能方面没有太大区别,但您仍然应该衡量这两种情况并亲自查看。

如果这是一个set/map/list的问题,它不会有任何区别。如果是vector/hash_set/hash_map/string的问题,第二个要么更快,要么速度相同。当然,这种速度差异只有在您执行大量操作时才会很明显(将 10,000 个整数推入一个vector 10,000 次大约是两倍快 - 3 秒和一些变化与 7 秒。

如果您正在执行诸如在数据结构中存储struct/class而不是指向一个的指针之类的操作,则此差异将更大,因为在每次调整大小时,都必须复制所有元素。

同样,在几乎所有情况下,这都无关紧要 - 在它确实重要的情况下,如果您正在优化并且您关心每一点性能,它就会出现。

第二个在时间上可能稍微好一点,但差异将非常小——代码仍然必须经历并释放集合中的每个项目,无论是重新创建还是清除它。

(从空间上讲,它们是相同的。

两者之间的性能差异很小。您应该根据代码的可读性和健壮性做出决定。

我认为第一个示例更具可读性和安全性 - 当您向循环中添加条件时,六个月后会发生什么,也许在某处继续 - 在第二个示例中,它将绕过 clear(),您将遇到一个错误。

你把你的集合放在堆栈上,因此分配成本几乎为零!

作为一般规则,将数据加载到容器中会产生内存分配成本。 通过重复使用容器来避免多次支付该成本要好得多。 如果您实际上知道有多少项,或者可以做出很好的猜测,则应预先在容器中预先分配空间。

如果要将对象插入容器中,

这一点尤其明显,因为您最终可能会支付大量额外的构造/销毁成本,因为容器意识到它太小,重新分配内存,并根据现有对象将新对象复制到新内存中。

始终预先分配和重用。 它节省了时间和内存。

区别很小,尽管您的第二个避免多次调用构造函数和析构函数。 另一方面,您的第一个短了一行,并保证容器在循环范围之外不可见。

Set 通常实现为一棵红色的黑色树。每个节点都是单独分配的,因此 set 不会从重用中受益。这就是为什么两种方法具有几乎相同的性能。调用"tempSet.clear()"应该花费与销毁对象大致相同的时间。第一种方法更好,因为它具有相同的性能并遵循更安全的编程风格。

您可以在此处找到有关其他容器的一般讨论:重用容器或创建新容器

我认为您可以为 STL 容器预先分配一定数量的元素,因此如果您知道容器中将有多少元素,则具有恒定的内存分配成本。