使用内置的std::list
而不是像C那样基于指针的自己的链表实现的优点/缺点是什么?
是否存在一些特殊情况,其中一个优于另一个?
使用std::list
而不是自己的链表实现有很多很好的理由:
-
std::list
是有保证的(通过c++标准库的执行标准)按照锡板上的说明工作(编号 -
std::list
不需要您花时间开发和测试。 -
std::list
是众所周知的,所以任何人都可以与之合作代码(或者你以后的生活)可以理解发生了什么不需要首先掌握自定义链表实现。
我真的想不出任何好的理由来使用你自己的自定义链表。
std::list
通常实现为双链表。如果你只需要一个单链表,你应该考虑std::forward_list
。
最后,如果你关心性能,你根本不应该使用链表。链表中的元素必须单独分配(并且通常插入在随机位置),因此处理链表通常会导致许多缓存丢失,每次都会造成性能损失。
通常,您希望使用std::list
,如@Walter所回答的。
然而,通过"侵入式"将next(和prev,如果有的话)指针直接集成到所包含的对象中来实现的列表,可以避免std::list
和其他STL容器的几个缺点,这些缺点可能与您相关,也可能与您无关(引用自Boost)。侵入性的文档):
- 一个对象只能属于一个容器:如果你想共享一个对象在两个容器之间,您必须存储它们的多个副本对象,或者需要使用指针容器:
std::list<Object*>
.- 使用动态分配来创建传递值的副本可以是一个某些应用程序的性能和大小瓶颈。[…]
- 只有对象的副本存储在非侵入性容器中。因此复制或移动构造函数和复制或移动赋值操作符是必需的。不可复制和不可移动的对象不能存储在非侵入性中容器。
在stl容器中存储派生对象是不可能的
第二点可能不适用于大多数典型的列表用法,在这些用法中,无论如何都要动态分配元素。
如果最后一点与您相关,那么您可能对Boost感兴趣。指针容器——尽管std::list<std::unique_ptr<Obj>>
通常也能很好地完成这项工作。
与其自己完全实现一个列表,不如看看前面提到的Boost。侵入性的图书馆。
Walter提供的答案涵盖了首选stl实现的主要原因。考虑经典C风格实现的主要原因是提高性能。这种性能提高的代价主要是潜在的错误。这可以通过测试和包含一些适当的断言(检查空指针…_
)来解决。与Walter回答中的陈述相反,在某些情况下,高性能列表是一个很好的数据结构选择。
如果你需要自定义列表的性能,但又想避免构建和测试自己的列表,请查看boost侵入列表(单链接和双链接):http://www.boost.org/doc/libs/1_39_0/doc/html/intrusive.html这将使您获得与自定义构造相同的性能,并且(几乎)具有stl版本的便利性。