链表使用 list<type> 和指针(经典 C)的区别
diffrence between using list<type> and pointers (classic C) for linked lists
使用内置 std::list
而不是像 C 中那样基于指针的自己的链表实现的 pros/cons 是什么?
是否存在某些特殊情况,其中一个优于另一个?
Walter 提供的答案涵盖了更喜欢 stl 实现的主要原因。考虑经典 C 风格实现的主要原因是提高性能。这种提高性能的代价主要是潜在的错误。这可以通过测试和包含一些适当的断言来解决(检查空指针..._
与 Walter 的回答中的陈述相反,在某些情况下,高性能列表是一个很好的数据结构选择。
如果您需要自定义列表的性能但又想避免构建和测试您自己的列表的工作,请查看增强侵入列表(单链接和双链接):
http://www.boost.org/doc/libs/1_39_0/doc/html/intrusive.html
这些将使您获得与自定义构造相同的性能,并且(几乎)具有 stl 版本的便利性。
有很多充分的理由使用 std::list
而不是您自己的链表实现:
std::list
得到保证(通过 c++ 标准库的
标准的实施)按照锡罐上的解释工作(无
标准的错误、异常安全和线程安全)。
std::list
不需要你花时间开发和
正在测试它。
std::list
是众所周知的,所以任何人都与
代码(或你以后的生活)可以理解发生了什么
无需首先掌握自定义链表
实施。
我真的想不出有什么好的理由使用您自己的自定义链表。
std::list
通常实现为双向链表。如果你只需要一个单链表,你应该考虑 std::forward_list
.
最后,如果您关心性能,则根本不应该使用链表。链表中的元素必须单独分配(并且经常插入到随机位置),因此处理链表通常会导致许多缓存未命中,每次都会影响性能。
通常,您希望使用 std::list
,如@Walter 所回答。
然而,通过 "intrusively" 将下一个(和上一个,如果有的话)指针直接集成到包含的对象中的列表可以避免 std::list
和其他 STL 容器的几个缺点,这可能与您相关,也可能不相关(引自 Boost.Intrusive documentation):
- An object can only belong to one container: If you want to share an object
between two containers, you either have to store multiple copies of those
objects or you need to use containers of pointers:
std::list<Object*>
.
- The use of dynamic allocation to create copies of passed values can be a
performance and size bottleneck in some applications. […]
- Only copies of objects are stored in non-intrusive containers. Hence copy
or move constructors and copy or move assignment operators are required.
Non-copyable and non-movable objects can't be stored in non-intrusive
containers.
- It's not possible to store a derived object in a STL-container while
retaining its original type.
第二点可能不适用于列表的大多数典型用法,无论如何您都会动态分配元素。
如果最后一点与您相关,您可能会对 Boost.PointerContainer 感兴趣 ‒ 尽管 std::list<std::unique_ptr<Obj>>
通常也能很好地完成工作。
与其自己完全实现一个列表,不如看看前面提到的 Boost.Intrusive 库。
使用内置 std::list
而不是像 C 中那样基于指针的自己的链表实现的 pros/cons 是什么?
是否存在某些特殊情况,其中一个优于另一个?
Walter 提供的答案涵盖了更喜欢 stl 实现的主要原因。考虑经典 C 风格实现的主要原因是提高性能。这种提高性能的代价主要是潜在的错误。这可以通过测试和包含一些适当的断言来解决(检查空指针..._
与 Walter 的回答中的陈述相反,在某些情况下,高性能列表是一个很好的数据结构选择。
如果您需要自定义列表的性能但又想避免构建和测试您自己的列表的工作,请查看增强侵入列表(单链接和双链接): http://www.boost.org/doc/libs/1_39_0/doc/html/intrusive.html 这些将使您获得与自定义构造相同的性能,并且(几乎)具有 stl 版本的便利性。
有很多充分的理由使用 std::list
而不是您自己的链表实现:
std::list
得到保证(通过 c++ 标准库的 标准的实施)按照锡罐上的解释工作(无 标准的错误、异常安全和线程安全)。std::list
不需要你花时间开发和 正在测试它。std::list
是众所周知的,所以任何人都与 代码(或你以后的生活)可以理解发生了什么 无需首先掌握自定义链表 实施。
我真的想不出有什么好的理由使用您自己的自定义链表。
std::list
通常实现为双向链表。如果你只需要一个单链表,你应该考虑 std::forward_list
.
最后,如果您关心性能,则根本不应该使用链表。链表中的元素必须单独分配(并且经常插入到随机位置),因此处理链表通常会导致许多缓存未命中,每次都会影响性能。
通常,您希望使用 std::list
,如@Walter 所回答。
然而,通过 "intrusively" 将下一个(和上一个,如果有的话)指针直接集成到包含的对象中的列表可以避免 std::list
和其他 STL 容器的几个缺点,这可能与您相关,也可能不相关(引自 Boost.Intrusive documentation):
- An object can only belong to one container: If you want to share an object between two containers, you either have to store multiple copies of those objects or you need to use containers of pointers:
std::list<Object*>
.- The use of dynamic allocation to create copies of passed values can be a performance and size bottleneck in some applications. […]
- Only copies of objects are stored in non-intrusive containers. Hence copy or move constructors and copy or move assignment operators are required. Non-copyable and non-movable objects can't be stored in non-intrusive containers.
- It's not possible to store a derived object in a STL-container while retaining its original type.
第二点可能不适用于列表的大多数典型用法,无论如何您都会动态分配元素。
如果最后一点与您相关,您可能会对 Boost.PointerContainer 感兴趣 ‒ 尽管 std::list<std::unique_ptr<Obj>>
通常也能很好地完成工作。
与其自己完全实现一个列表,不如看看前面提到的 Boost.Intrusive 库。