简体   繁体   English

FIFO实现

[英]FIFO implementation

While implementing a FIFO I have used the following structure: 在实现FIFO时,我使用了以下结构:

struct Node
{
    T info_;
    Node* link_;
    Node(T info, Node* link=0): info_(info), link_(link)
    {}
};

I think this a well known trick for lots of STL containers (for example for List). 我认为这是许多STL容器(例如List)的众所周知的技巧。 Is this a good practice? 这是一个好习惯吗? What it means for compiler when you say that Node has a member with a type of it's pointer? 当你说Node有一个带有类型指针的成员时,它对编译器意味着什么? Is this a kind of infinite loop? 这是一种无限循环吗?

And finally, if this is a bad practice, how I could implement a better FIFO. 最后,如果这是一个不好的做法,我如何能够实现更好的FIFO。

EDIT: People, this is all about implemenation. 编辑:人们,这完全是关于实施。 I am enough familiar with STL library, and know a plenty of containers from several libraries. 我对STL库非常熟悉,并且知道来自多个库的大量容器。 Just I want to discuss with people who can gave a good implementation or a good advice. 我想与能够提供良好实施或良好建议的人讨论。

Is this a good practice? 这是一个好习惯吗?

I don't see anything in particular wrong with it. 我没有看到任何特别的错误。

What it means for compiler when you say that Node has a member with a type of it's pointer? 当你说Node有一个带有类型指针的成员时,它对编译器意味着什么?

There's nothing wrong with a class storing a pointer to an object of the same class. 存储指向同一类对象的指针的类没有任何问题。

And finally, if this is a bad practice, how I could implement a better FIFO. 最后,如果这是一个不好的做法,我如何能够实现更好的FIFO。

I'd use std::queue ;) 我用std::queue ;)

Obviously you are using linked-list as the underlying implementation of your queue. 显然,您使用链接列表作为队列的底层实现。 There's nothing particularly bad about that. 这没什么特别糟糕的。

Just FYI though, that in terms of implementation, std::queue itself is using std::deque as its underlying implementation. 仅供参考,在实现方面,std :: queue本身使用std :: deque作为其底层实现。 std::deque is a more sophisticated data structure that consists of blocks of dynamic arrays that are cleverly managed. std :: deque是一个更复杂的数据结构,由巧妙管理的动态数组块组成。 It ends up being better than linked list because: 它最终比链表更好,因为:

  1. With linked-list, each insertion means you have to do an expensive dynamic memory allocation. 使用链表,每次插入意味着您必须进行昂贵的动态内存分配。 With dynamic arrays, you don't. 对于动态数组,您不需要。 You only allocate memory when the buffer has to grow. 只有在缓冲区必须增长时才分配内存。
  2. Array elements are contiguous and that means elements access can be cached easily in hardware. 数组元素是连续的,这意味着元素访问可以很容易地在硬件中缓存。

您可以使用现有的FIFO, std :: queue

This is one good way of implementing a node. 这是实现节点的一种好方法。 The node pointer is used to create the link to the next node in the container. 节点指针用于创建指向容器中下一个节点的链接。 You're right though, it can be used to create a loop. 你是对的,它可以用来创建一个循环。 If the last node in the container references the first, iterating that container would loop through all of the nodes. 如果容器中的最后一个节点引用第一个节点,则迭代该容器将遍历所有节点。

For example, if the container is a FIFO queue the pointer would reference the next node in the queue. 例如,如果容器是FIFO队列,则指针将引用队列中的下一个节点。 That is, the value of link_ would be the address of another instance of class Node . 也就是说, link_的值将是Node类的另一个实例的地址。

If the value type T implemented an expensive copy constructor, a more efficient Node class would be 如果值类型T实现了昂贵的复制构造函数,则会有更高效的Node

struct Node
{
    T * info_;
    Node* link_;
    Node(T * info, Node* link=0): info_(info), link_(link)
    {}
};

Note that info_ is now a pointer to an instance of T . 请注意, info_现在是指向T实例的指针。 The idea behind using a pointer is that assigning a pointer is less expensive than copying complex objects. 使用指针的想法是指定指针比复制复制对象便宜。

Pointers to objects of type that is being declared is fine in both C and C++. 指向正在声明的类型的对象的指针在C和C ++中都很好。 This is based on the fact that pointers are objects of fixed size (say, always 32-bit integers on 32-bit platform) so you don't need the full size of the pointed-to type to be known. 这是基于指针是固定大小的对象(例如,在32位平台上始终是32位整数)的事实,因此您不需要知道指向类型的完整大小。

In fact, you don't even need a full type declaration to declare a pointer. 实际上,您甚至不需要完整的类型声明来声明指针。 A forward declaration would suffice: 前瞻性声明就足够了:

class A; // forward declared type

struct B
{
    A* pa; //< pointer to A - perfectly legal
};

Of course, you need a full declaration in scope at the point where you actually access members: 当然,在实际访问成员时,您需要在范围内进行完整声明:

#include <A.hpp> // bring in full declaration of class A
...
B b;
b.pa = &a; // address of some instance of A
...
b.pa->func(); // invoke A's member function - this needs full declaration

For FIFO look into std::queue . 对于FIFO,请查看std::queue Both std::list , std::deque , and std::vector could be used for that purpose, but also provide other facilities. std::liststd::dequestd::vector都可以用于此目的,但也提供其他功能。

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

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