阅读后this question看着一些 results here ,似乎应该完全避免使用 C++ 中的列表。我一直希望链表会成为我只需要遍历所有内容的情况下的首选容器,因为插入是指针操作的问题,并且永远不需要重新分配。
显然,由于“缓存局部性”,列表的迭代速度非常慢,因此必须使用更少的保留内存或更快的添加(从第二个链接看来,这似乎并没有那么快)带来的任何好处都不会似乎不值得。
话虽如此,从性能的角度来看,我什么时候应该使用 std::list
而不是 std::deque
或者如果可能的话,使用 std::vector
?
顺便说一句,std::forward_list
是否也会有很多缓存未命中?
最佳答案
std::list
在一些极端情况下很有用。
但是,C++ 顺序容器的一般规则是“如果您的算法兼容,请使用 std::vector
。如果您的算法不兼容,请修改您的算法以便您可以使用 std::vector
."
存在异常(exception),这里试图详尽列出 std::list
是更好选择的原因:
当您需要 (A) 插入到容器的中间并且 (B) 您需要内存中的每个对象位置保持稳定时。要求 (B) 通常可以通过包含指向元素的指针组成的不稳定容器来删除,因此这不是使用
std::list
的强烈理由。当您需要 (A) 在容器中间插入或删除 (B) 数量级时,其频率比您需要遍历容器的频率高出几个数量级。这也是一个极端的极端情况:为了从
list
中找到要删除的元素,您通常需要迭代!
导致
您需要 (A) 在容器中间插入或删除,并且 (B) 让所有其他元素的迭代器保持有效。这最终成为案例 1 和案例 2 的隐藏要求:当您没有持久迭代器时,删除或插入的频率比迭代的频率高,并且迭代器和对象的稳定性高度相关。
最后一种情况,就是拼接的情况曾经是使用
std::list
的理由。
回到 C++03,std::list::splice
的所有版本(理论上)都可以在 O(1) 时间内完成。然而,非常有效的 splice
形式要求 size
是一个 O(n) 操作。 C++11 要求 list
上的 size
为 O(1),因此 splice
的极限效率仅限于“拼接整个其他列表”和“自拼接子列表”的情况。在单个元素拼接的情况下,这只是插入和删除。在子范围拼接的情况下,代码现在必须访问拼接中的 每个 节点来计数它们,以便将 size
保持为 O(1)(除了在自拼接)。
所以,如果你只做整个-list
拼接,或者自列表子范围splice
s,list
可以做很多这些操作比其他非列表容器更快。
关于c++ - 有没有理由使用 std::list?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18449038/