在编程中,我们面临各种需要使用中间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 ++编译器的当前状态,哪种方法在时间和空间复杂性方面更好?
答案 0 :(得分:15)
第一个版本是正确的。它几乎在所有方面都比较简单。更容易编写,更易于阅读,更易于理解,更易于维护等....
第二个版本可能更快,但之后可能不会。在使用之前,您需要证明它具有显着优势。在大多数非平凡的情况下,我猜测两者之间不会有可衡量的性能差异。
有时在嵌入式编程中,避免将东西放在堆栈上会很有用;在这种情况下,第二个版本是正确的。
默认情况下使用第一个版本;只有当你能给出一个很好的理由时才使用第二个(如果原因是表现,那么你应该有证据证明这个好处很重要。)
答案 1 :(得分:7)
我说第一个更容易出错。你不必记得清除它(它只会超出范围并完成)。 : - )
在性能方面没有太大区别,但你应该测量这两种情况并亲自看看。
答案 2 :(得分:4)
如果这是set/map/list
的问题,则不会有任何区别。如果它是vector/hash_set/hash_map/string
的问题,则第二个将更快或相同的速度。当然,如果你进行了大量的操作,这种速度的差异将是显而易见的(10,000次推入vector
10,000次约为两倍--3秒和一些变化与7秒。 )。
如果你正在做一些事情,比如在你的数据结构中存储struct/class
而不是指向一个,那么这种差异会更大,因为在每次调整大小时,你必须复制所有元素。
同样,几乎在所有情况下,都无关紧要 - 在重要的情况下,如果您正在优化,它会显示出来,并且您关心每一点性能。
答案 3 :(得分:2)
第二个可能稍微好一点,但差异将极小 - 代码仍然必须通过并释放集合中的每个项目,无论它是重新创建还是清除它
(在空间方面,他们将是相同的。)
答案 4 :(得分:1)
两者之间的性能差异很小。您应该根据代码可读性和稳健性做出决定。
我认为第一个例子更具可读性和安全性 - 当你在循环中添加条件时,六个月内会发生什么,也许在某处有一个继续 - 在第二个例子中,它将绕过clear(),你会有一个错误。
答案 5 :(得分:1)
你把你的设置放在堆栈上,因此分配成本几乎为零!
答案 6 :(得分:0)
作为一般规则,将数据加载到容器中会产生内存分配成本。通过重新使用容器避免多次支付该成本要好得多。如果您确实知道有多少项,或者可以做出好的猜测,那么您应该预先在容器中预先分配空间。
特别值得注意的是,如果要将对象插入容器中,因为最终会支付大量的额外构造/销毁成本,因为容器意识到它太小,重新分配内存,并且复制构造新对象到基于现有对象的新内存。
始终预先分配和重复使用。它节省了时间和记忆。
答案 7 :(得分:0)
尽管你的第二个避免多次调用构造函数和析构函数,但差别很小。另一方面,你的第一个是短一行,并保证容器在循环范围之外不可见。
答案 8 :(得分:0)
Set通常实现为红黑树。每个节点都是单独分配的,因此设置不会从重用中受益。这就是为什么两种方法都具有几乎相同的性能。调用“tempSet.clear()”应该大约与销毁对象的时间相同。第一种方法更好,因为它具有相同的性能并遵循更安全的编程风格。
您可以在此处找到有关其他容器的一般性讨论:Reusing a container o creating a new one
答案 9 :(得分:-1)
我认为您可以为STL容器预先分配一定数量的元素,因此如果您知道容器中有多少元素,则会有一个恒定的内存分配成本。