C++ C++;STL:清理后的集装箱再利用或再利用?

C++ C++;STL:清理后的集装箱再利用或再利用?,c++,stl,complexity-theory,C++,Stl,Complexity Theory,在编程中,我们面临各种情况,需要使用中间STL容器,如下例所示: while(true) { set < int > tempSet; for (int i = 0; i < n; i ++) { if (m.size() == min && m.size() <= max) { tempSet.insert(i); } } //Some co

在编程中,我们面临各种情况,需要使用中间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
}
while(true)
{
设置tempSet;
对于(int i=0;i如果(m.size()==min&&m.size()第二个选项在时间上可能会稍微好一点,但差异将非常小——代码仍然必须遍历并释放集合中的每个项目,而不管它是在重新创建还是清除它


(就空间而言,它们是相同的。)

一般来说,将数据加载到容器中会产生内存分配成本。最好通过重用容器避免多次支付该成本。如果您确实知道有多少项,或者可以很好地猜测,您应该提前在容器中预先分配空间

特别值得注意的是,如果将对象插入到容器中,因为容器意识到它太小,会重新分配内存,并基于现有对象将新对象复制到新内存中,因此最终可能会支付大量额外的构造/销毁成本


总是预先分配和重用。这样可以节省时间和内存。

如果这是一个
set/map/list
的问题,它不会有任何区别。如果这是一个
vector/hash\u set/hash\u map/string
的问题,第二个会更快或相同的速度。当然,只有当你在做v>时,速度上的差异才会明显非常多的操作(10000个整数被推到
向量中
10000次大约是速度的两倍-3秒,有些变化是7秒)

如果要在数据结构中存储
struct/class
,而不是指针,这种差异会更大,因为每次调整大小时,都必须复制所有元素


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

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


就性能而言,没有太大的区别,但是您应该测量这两种情况并亲自查看。

差别很小,尽管您的第二种情况避免多次调用构造函数和析构函数。另一方面,您的第一种情况缩短了一行,并保证容器不可见le超出了循环的范围。

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

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

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


默认情况下使用第一个版本;只有在您能够给出一个很好的理由时才使用第二个版本(如果原因是性能,那么您应该有证据证明这一好处是显著的)。

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


我认为第一个示例更具可读性和安全性-当您在循环中添加一个条件时,六个月后会发生什么,可能在其中某个地方有一个continue-在第二个示例中,它将绕过clear()您将有一个bug。

您正在将集合放在堆栈上,因此分配成本几乎为零!

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

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


你可以在这里找到关于其他容器的一般性讨论:

我不认为你可以在一个集合中预先分配空间。是的,我明白了。你可能需要对分配器做些傻事,然后才能得到一个合适的预分配。我运行了一个测试。最大大小是巨大的。在这种情况下这不是一个问题。这个问题是关于集合,而不是向量。同样对于向量,我也在讨论是否注意到速度的差异:向量应该以指数形式增长(通常每次增长两倍),因此分配的数量是摊销的。这两个问题都不是特定的。如果你花时间实际运行一些速度测试,在这种情况下,它确实很重要,你会注意到一个巨大的性能打击。伤害的不是分配,而是realloc之后的memcpy。@ChrisJester-Young:是的,分配的数量是摊销的ed,但比
Mlog(n)更好
log(n)
allocations
。集合对象本身的分配成本接近于零,但其中的项目仍然是从堆中分配的。@Head Geek:集合中对象的构造/销毁在两个示例中都是相同的-唯一的区别是集合对象本身的构造/销毁。因此ypnos的观点是有效的。@Mike B:对不起,但我不明白你的意思。正如我读到的,ypnos谈论的是分配成本——为对象分配内存所需的时间——所以
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
}