简体   繁体   English

如何理解C++中链表的freelist实现?

[英]How to understand freelist implementation for linked-list in C++?

I don't understand the last few lines here.我不明白这里的最后几行。

// Singly linked list node with freelist support
template<typename Elem> class Link {
private:
  static Link<Elem>* freelist; // Reference to freelist head
public:
  Elem element;                // Value for this node
  Link* next;                  // Point to next node in list

  // Constructors
  Link(const Elem& elemval, Link* nextval = NULL)
    { element = elemval; next = nextval; }
  Link(Link* nextval = NULL) { next = nextval; }

  void* operator new(size_t) { // Overloaded new operator
    if (freelist == NULL) return ::new Link; // Create space
    Link<Elem>* temp = freelist; // Can take from freelist
    freelist = freelist->next;
    return temp;                 // Return the link
  }

  // Overloaded delete operator
  void operator delete(void* ptr) {
    ((Link<Elem>*)ptr)->next = freelist; // Put on freelist
    freelist = (Link<Elem>*)ptr;
  }
};

// The freelist head pointer is actually created here
template<typename Elem>
Link<Elem>* Link<Elem>::freelist = NULL;

In particular, why do we need to define a pointer to a pointer in the last line?特别是,为什么我们需要在最后一行定义一个指向指针的指针? Link<Elem>::freelist is already a pointer, so why do we need to set another pointer to that pointer to NULL ? Link<Elem>::freelist已经是一个指针,那么为什么我们需要将另一个指向该指针的指针设置为NULL呢?

Can someone clear this up for me?有人可以帮我解决这个问题吗? I'm very confused.我很困惑。

Distilling your example down, this is what you have:提炼你的例子,这就是你所拥有的:

class Link {
    static Link* freelist;
}

Link* Link::freelist = NULL;

As the comment mentions, "The freelist head pointer is actually created here".正如评论中提到的,“freelist 头指针实际上是在这里创建的”。 The first part is a declaration of the static variable freelist but it does not actually define it.第一部分是静态变量freelist声明,但实际上并没有定义它。 The definition below mimics the declaration (and gives it a value).下面的定义模仿声明(并给它一个值)。 It does not add another level of pointer.它不会添加另一个级别的指针。

Not only the last two lines should raise questions, but the implementation of the operator new .不仅最后两行应该引起问题,而且operator new的实现。

Let's consider the following code:让我们考虑以下代码:

struct S { 
    // ... 
};

auto list = new List<S>;

Here new List<S> will call List<S>::operator new to allocate raw memory.这里new List<S>将调用List<S>::operator new来分配原始内存。 It will call global ::new , and that global ::new will allocate memory (with ::operator new ) and construct Link , ie S and Link* , in it.它将调用 global ::new ,并且 global ::new将分配内存(使用::operator new )并在其中构造Link ,即SLink* Then our local new will construct Link again at the same memory location.然后我们的本地new将在相同的内存位置再次构造Link As a result, S will be constructed twice at the same memory location.因此, S将在同一内存位置构造两次。 Depending on S , this can lead to undefined behaviour and/or memory leaks.根据S ,这可能导致未定义的行为和/或内存泄漏。

Simple example:简单的例子:

struct S {
    S()  { std::cout << "ctor at " << this << '\n'; }
    ~S() { std::cout << "dtor at " << this << '\n'; }
};

int main() {
    auto list = new Link<S>;
    delete list;
}

Sample output:示例输出:

ctor at 0x24b8e80
ctor at 0x24b8e80
dtor at 0x24b8e80

Declaration of static non-const member of class requires exactly one out-of-line definition.类的静态非常量成员的声明只需要一个外部定义。 Static members do not use their class object's storage, so you have to declare and initialize its own separately.静态成员不使用它们的类对象的存储,所以你必须单独声明和初始化它自己的。

class Link {
    static Link* freelist; // declaring that such object exists
};

// Shouldn't appear in a header file  to not break One Definition Rule
Link* Link::freelist = nullptr; // initialization

freelist is actually a "global" variable which could be accessed though context of class Link, eg Link::freelist if it was public. freelist 实际上是一个“全局”变量,它可以通过类 Link 的上下文访问,例如Link::freelist如果它是公共的。 In this particular case , it's just being shared between all instances of class object.在这种特殊情况下,它只是在类对象的所有实例之间共享。

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

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