c++ - 有没有理由使用 std::list?

标签 c++ stl containers

阅读后this question看着一些 results here ,似乎应该完全避免使用 C++ 中的列表。我一直希望链表会成为我只需要遍历所有内容的情况下的首选容器,因为插入是指针操作的问题,并且永远不需要重新分配。

显然,由于“缓存局部性”,列表的迭代速度非常慢,因此必须使用更少的保留内存或更快的添加(从第二个链接看来,这似乎并没有那么快)带来的任何好处都不会似乎不值得。

话虽如此,从性能的角度来看,我什么时候应该使用 std::list 而不是 std::deque 或者如果可能的话,使用 std::vector?

顺便说一句,std::forward_list 是否也会有很多缓存未命中?

最佳答案

std::list 在一些极端情况下很有用。

但是,C++ 顺序容器的一般规则是“如果您的算法兼容,请使用 std::vector。如果您的算法不兼容,请修改您的算法以便您可以使用 std::vector."

存在异常(exception),这里试图详尽列出 std::list 是更好选择的原因:

  1. 当您需要 (A) 插入到容器的中间并且 (B) 您需要内存中的每个对象位置保持稳定时。要求 (B) 通常可以通过包含指向元素的指针组成的不稳定容器来删除,因此这不是使用 std::list 的强烈理由。

  2. 当您需要 (A) 在容器中间插入或删除 (B) 数量级时,其频率比您需要遍历容器的频率高出几个数量级。这也是一个极端的极端情况:为了从 list 中找到要删除的元素,您通常需要迭代!

导致

  1. 您需要 (A) 在容器中间插入或删除,并且 (B) 让所有其他元素的迭代器保持有效。这最终成为案例 1 和案例 2 的隐藏要求:当您没有持久迭代器时,删除或插入的频率比迭代的频率高,并且迭代器和对象的稳定性高度相关。

  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 拼接,或者自列表子范围splices,list 可以做很多这些操作比其他非列表容器更快。

关于c++ - 有没有理由使用 std::list?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18449038/

相关文章:

c++ - 处理特定类型元素的任何容器的非模板函数

c++ - 如何搜索一个字符串是否是集合中存储的字符串的前缀?

c++ - 为什么 std::tuple 的 get helper 返回右值引用而不是值

C++ STL算法在列表中添加元素

c++ - 使用 new 时将指针转换为 void* 的优势

linker - docker链接容器所有端口关闭

c++ - 禁用/隐藏 CListCtrl MFC 中的项目

c++ - (clang/llvm-mc/lld) Hello World (x86-64 windows & linux)

c++ - 根据模板变量类型执行不同的方法

c++ - 为什么 vector<> 和 list<> 容器中的 push_back 不返回对插入元素的引用?