是否应弃用 std::list ?

Posted

技术标签:

【中文标题】是否应弃用 std::list ?【英文标题】:Should std::list be deprecated? 【发布时间】:2012-11-26 14:42:55 【问题描述】:

根据 Bjarne Stroustrup 的 slides 来自他的 Going Native 2012 keynote,std::list 中的插入和删除在现代硬件上非常低效:

向量节拍列表海量用于插入和删除

如果确实如此,std::list 还剩下哪些用例?那不应该被弃用吗?

【问题讨论】:

不可失效的迭代器和引用,只要该特定元素未被删除。 您假设选择列表的唯一原因是插入性能。事实上,我认为存储持久性是人们应该选择列表的主要原因。 我也质疑这些结果。从链表中插入和删除应该是O(1),而对于向量来说是O(n) @Walter 该图实际上只是邀请查看链接的幻灯片。 该图涉及两个操作的总和。找到要删除的元素,然后将其删除。在这两种情况下,结果都是 O(n)。删除对于列表来说是 O(1),对于向量来说是 O(n),但是向量的操作在列表的一半以下有一个常数因子。该测试是有效的,因为您通常必须在擦除之前找到要擦除的元素。它不会过时,因为有时这不是真的。 【参考方案1】:

std::list 是一个双端队列,它有push_front()pop_front()。尽管它可能不是双端队列的最佳选择,但它仍然具有这样的利基角色。

链表与树数据结构有关。两者都包含链接。如果我们弃用std::list,那么基于树的容器呢?

【讨论】:

【参考方案2】:

向量和列表解决不同的问题。 List 保证迭代器在插入和删除其他元素时永远不会失效。 Vector 不做这样的保证。

这不仅仅与性能有关。所以答案是否定的。列表不应被弃用。

编辑除此之外,C++ 并非专为在“现代硬件”上工作而设计。它旨在用于比这更广泛的硬件。我是金融行业的程序员,我使用 C++,但其他领域,如嵌入式设备、可编程控制器、心肺机和无数其他领域也同样重要。 C++ 语言的设计不应该单独考虑到某些领域的需求和某些类别的硬件的性能。仅仅因为 I 可能不使用列表并不意味着它应该从语言中被弃用。

【讨论】:

虽然,不幸的是,当标准的人决定 size 必须是 O(1) 时,list 确实受到了抨击。 splice 是以前使用列表的最佳理由之一,现在它没有那么有用了,如果你需要它,你最好制作自己的容器:x @MatthieuM。 C++11 添加了std::forward_list 来填补这个空白。 std::list 不会使迭代器无效是不正确的。指向已删除节点的所有迭代器都将失效。实际上,这意味着您必须保留一个迭代器列表,就像您在 std::vector 的情况下所做的那样。 std::list 在几乎任何硬件上都很慢,不仅仅是现代的。您很难找到std::list 在内存或执行速度方面优于std::vector 的用例和硬件组合。【参考方案3】:

向量是否优于列表还取决于元素的类型。例如,对于int 元素,向量确实非常快,因为大多数数据都适合 CPU 缓存,并且 SIMD 指令可用于数据复制。所以vector的O(n)复杂度影响不大。

但是对于更大的数据类型,复制不会转换为流操作,而是必须从各处获取数据?此外,没有大型 CPU 缓存并且可能还缺少 SIMD 指令的硬件呢? C++ 不仅用于现代台式机和工作站机器。弃用 std::list 是不可能的。

Stroustrup 在该演示文稿中所说的是,在您为数据选择 std::list 之前,您应该确保它是您的特定情况的正确选择。换句话说,基准和配置文件。它绝对不是说你应该总是选择 std::vector。

【讨论】:

【参考方案4】:

当然不是。 std::list 是一种不同的数据结构。比较不同的数据结构可以很好地表明其属性、优点或缺点。但每种数据结构都有其优势。

【讨论】:

【参考方案5】:

不,尤其是不基于一个特定的图表。在某些情况下,列表会比向量表现更好。见:http://www.baptiste-wicht.com/2012/12/cpp-benchmark-vector-list-deque/

正如其他人所提到的,这忽略了非性能差异。

Bjarne 在那次谈话中的观点不是你不应该使用列表。正是人们对 list 的性能做出了太多的假设,结果往往是错误的。他只是在证明向量应该始终是您的默认首选容器类型的立场,除非您确实发现需要列表的性能或其他语义特征。

【讨论】:

您提供的基准测试表明,std::list 只有在元素很大时才有机会对抗std::vector。此时最好将元素分配到堆上并将std::unique_ptr 存储在向量中。

以上是关于是否应弃用 std::list ?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在打字稿中将某些内容标记为已弃用?

是否已弃用 SQL Server 时间戳以及替换时使用啥

DTD 是不是已弃用?

检查 UILocalNotification 弃用后是不是启用用户通知

tslint 扩展将订阅的非弃用版本标识为弃用

load() 方法已弃用?