简体   繁体   English

侵入式列表

[英]Intrusive lists

I've not been able to find too much information about them online.我在网上找不到太多关于它们的信息。 What are they and when are they typically used?它们是什么以及它们通常何时使用?

Thanks.谢谢。

An intrusive list is one where the pointer to the next list node is stored in the same structure as the node data.侵入式列表是指向下一个列表节点的指针存储在与节点数据相同的结构中的列表。 This is normally A Bad Thing, as it ties the data to the specific list implementation.这通常是一件坏事,因为它将数据与特定的列表实现联系起来。 Most class libraries (for example, the C++ Standard Library) use non-intrusive lists, where the data knows nothing about the list (or other container) implementation.大多数类库(例如,C++ 标准库)使用非侵入式列表,其中数据对列表(或其他容器)实现一无所知。

I actually like the intrusive model.我实际上喜欢侵入式模型。

  1. It's better on memory (not many small allocations for things to point at other things)它在内存上更好(用于指向其他事物的小分配不多)
  2. It allows you to have an object that exist in multiple containers at once.它允许您同时拥有一个存在于多个容器中的对象。
  3. It allows you to find an element with one search mode (hash) but then find the next element in lexographic order它允许您使用一种搜索模式(哈希)查找元素,然后按字典顺序查找下一个元素
    • This is not the same as #2, but it can be accomplished with boost's multi_index_container , but note that multi_index_container has certain shortcomings that are non-issues with intrusive containers.这是一样的#2,但它可以完成升压转换器的multi_index_container ,但要注意multi_index_container有一定的缺点是无问题进行介入式容器。

Intrusive is GOOD侵入性是好的

...you just need to know what you are doing (which is true for any container). ...你只需要知道你在做什么(这适用于任何容器)。

It surprising how so many people get this completely wrong (such as the answer from Ziezi).令人惊讶的是,这么多人完全错了(例如 Ziezi 的回答)。 People seem to over-complicate things when it's really pretty simple.当事情真的很简单时,人们似乎把事情复杂化了。

In an intrusive linked list there is no explicit 'Node' struct/class.在侵入式链表中,没有明确的“节点”结构/类。 Instead the 'Data' struct/class itself contains a next and prev pointer/reference to other Data in the linked list.相反,“数据”结构/类本身包含指向链表中其他数据的下一个和上一个指针/引用。

For example (intrusive linked list node):例如(侵入式链表节点):

struct Data { 
   Data *next; 
   Data *prev; 
   int fieldA; 
   char * fieldB; 
   float fieldC; 
}  

Notice how the next and prev pointers sit alongside and intrude on the private data fields of the entity such as fieldA.请注意 next 和 prev 指针如何并排并侵入实体的私有数据字段,例如 fieldA。 This 'violates' the separation of concerns enforced by standard linked lists (see below) but has benefits in greatly reducing the amount of list walking to locate specific nodes as well as lower memory allocations.这“违反”了由标准链表(见下文)强制执行的关注点分离,但有利于大大减少列表遍历以定位特定节点的数量以及较低的内存分配。

In an intrusive linked list, the 'linked list' itself is often virtual, there is normally no need to create a linked list struct/class at all.在侵入式链表中,“链表”本身通常是虚拟的,通常根本不需要创建链表结构/类。

Instead you can simply store a head pointer to the first Data item in some owner/manager.相反,您可以简单地将指向第一个数据项的头指针存储在某个所有者/管理器中。 This manager also contains Add/Remove functions to update pointers as needed.该管理器还包含添加/删除函数以根据需要更新指针。 For more info see https://gameprogrammingpatterns.com/spatial-partition.html有关更多信息,请参阅https://gameprogrammingpatterns.com/spatial-partition.html

Having a single pair of next/prev pointers dictates that each object can only belong to one list.拥有一对 next/prev 指针表明每个对象只能属于一个列表。 However you can of course add multiple pairs of next/prev pointers as needed (or define an array of next/prev pointers) to support objects in multiple lists.但是,您当然可以根据需要添加多对 next/prev 指针(或定义 next/prev 指针数组)以支持多个列表中的对象。

In a non-intrusive (ie standard) linked list the next/prev pointers are part of a dedicated 'node' entity and the actual Data entity simply a field in that node.在非侵入式(即标准)链表中,next/prev 指针是专用“节点”实体的一部分,而实际数据实体只是该节点中的一个字段。

For example (non intrusive linked list node and data):例如(非侵入式链表节点和数据):

struct Data { 
   int fieldA; 
   char * fieldB; 
   float fieldC; 
}  

struct Node { 
   Node *next; 
   Node *prev; 
   Data *data; 
}  

Notice how the next/prev pointers do not intrude on the actual Data entity and the separation of concerns is maintained.请注意 next/prev 指针如何不侵入实际的 Data 实体并保持关注点分离。

Update:更新:

You may see other sites such as https://www.data-structures-in-practice.com/intrusive-linked-lists/ use a 'List' struct (actually a Node) that contains next/prev pointers and is the single intrusive field in the 'Data' struct/class.您可能会看到其他站点,例如https://www.data-structures-in-practice.com/intrusive-linked-lists/使用包含 next/prev 指针的“列表”结构(实际上是一个节点),并且是单个“数据”结构/类中的侵入性字段。

This does hide the next/prev pointers from the Data, however it suffers from the need to perform pointer arithmetic simply to access the actual Data associated with the List (Node).这确实隐藏了数据的下一个/上一个指针,但是它需要执行指针算术来访问与列表(节点)关联的实际数据。

This approach adds needless complexity in my option (over simply embedding next/prev fields directly) just for the the dubious goal of hiding the next/prev pointers.这种方法在我的选项中增加了不必要的复杂性(而不是简单地直接嵌入 next/prev 字段),只是为了隐藏 next/prev 指针的可疑目标。 If you need intrusive lists, keep them simple as possible.如果您需要侵入式列表,请尽可能使它们简单。 (Also, in managed memory languages it is difficult or impossible to do pointer arithmetic anyway.) (此外,在托管内存语言中,无论如何都很难或不可能进行指针运算。)

Here is a brief description that is valid for lists as well:以下是对列表也有效的简要说明:

I. Intrusive containers. I. 侵入式容器。

Object to be stored contains additional information to allow integration in container.要存储的对象包含允许在容器中集成的附加信息。 Example:例子:

\nstruct Node结构节点\n{ {\n    Node* next;下一个节点*; // additional // 额外的\n    Node* prev;节点*上一个; // information // 信息 \n    T data;数据;\n} } \n

1. Pros: 1. 优点:

  • stores the objects themselves.存储对象本身。

  • doesn't involve memory management.不涉及内存管理。

  • iteration is faster.迭代速度更快。
  • better exception guarantees.更好的异常保证。
  • predictability in insertion and deletion of objects.对象插入和删除的可预测性。 (no additional (non-predictable) memory management is required.) (不需要额外的(不可预测的)内存管理。)
  • better memory locality.更好的内存局部性。

2. Cons: 2. 缺点:

  • contains additional data for container integration.包含用于容器集成的附加数据。 (every store type must be adapted (modified) to the container requirements.) (每种商店类型都必须适应(修改)到容器要求。)
  • caution with possible side effects when changing the contents of the stored object.(especially for associative containers.)更改存储对象的内容时要小心可能产生的副作用。(特别是对于关联容器。)
  • lifetime management of the inserted object, independently from the container.插入对象的生命周期管理,独立于容器。
  • object can be possibly disposed before erased from the container leading to iterator invalidation.对象可能会在从容器中擦除之前被释放,从而导致迭代器失效。
  • intrusive containers are NON-copyable and NON-assignable.侵入式容器是不可复制和不可分配的。

II.二、 Non-instrusive containers (C++ standard containers)非侵入式容器(C++ 标准容器)

Object doesn't "know" and contain details about the container in which is to be stored.对象不“知道”并包含有关要存储在其中的容器的详细信息。 Example:例子:

\nstruct Node结构节点\n{ {\n    T data;数据;\n} }

1. Pros: 1. 优点:

  • does not containe additional information regarding the container integration.不包含有关容器集成的附加信息。
  • object's lifetime managed by the container.由容器管理的对象的生命周期。 (less complex.) (不太复杂。)

2. Cons: 2. 缺点:

  • store copies of values passed by the user.存储用户传递的值的副本。 (inplace construction possible.) (可以就地施工。)
  • an object can belong only to one container.一个对象只能属于一个容器。 (or the contaier should store pointers to objects.) (或者容器应该存储指向对象的指针。)
  • overhead on storing copies.存储副本的开销。 (bookkeeping on each allocation.) (每次分配的簿记。)
  • non-copyable or non-movable objects CAN'T be stored in non-intrusive containers. 不可复制或不可移动的对象不能存储在非侵入式容器中。
  • can't store derived object and still maintain its original type.无法存储派生对象并仍保持其原始类型。 (slicing - looses polymorphism.) (切片 - 失去多态性。)

Intrusives lists are lists where objects are themselves heads or cells of lists.侵入式列表是对象本身是列表的头部或单元的列表。 They are good or bad things depending of context.根据上下文,它们是好是坏。

Inside some defined module (unsecable group of classes working together) it may be the BEST mean to tie relationships between classes.在某些已定义的模块(一起工作的不可分割的类组)中,它可能是将类之间的关系联系起来的最佳方法。 They allow no-cost direct and full management of common relationships like unicity (ex: apples does not apears two times in appletrees, and this does not need any key for this, and apples does not belong to two distincts trees), they are navigable in both directions (direct accès to appletree given an apple and to apples given some appletree).它们允许免费直接和完全管理诸如 unicity 之类的常见关系(例如:苹果不会在苹果树中出现两次,这不需要任何密钥,并且苹果不属于两个不同的树),它们是可导航的在两个方向(直接访问给定一个苹果的苹果树和给定一些苹果树的苹果)。 All basic operations are O(1) (no search in some external container).所有基本操作都是 O(1)(不在某些外部容器中搜索)。

Intrusive list are VERY BAD between two Modules.两个模块之间的侵入式列表非常糟糕。 Because they will be tied together, and modules justification is management of code independance.因为它们将被捆绑在一起,并且模块的理由是代码独立性的管理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM