内容简介
最近在看一个开源库的代码,用 C 实现了一种通用的双向链表结构。设计思想是将prev
和next
抽取成struct Node
,针对Node
编写通用的双向链表类。当需构造特定类型的链表时,首先在其中定义一个Node
类型的成员,然后使用CONTAINER_OF
宏借助Node
的成员的关系得到特定类型链表关系,无需再为特定类型链表编写专用函数。
本文以IntNode
为例,演示通用Node
双向链表类和CONTAINER_OF
宏的使用。其实,写这篇文章就是为了介绍CONTAINER_OF
这个宏。
设计实现
Node 节实现
struct Node {
Node *prev;
Node *next;
};
通用的双向链表类实现
本文的重点不在于双向链表,直接附上一种双向循环链表XList
的实现。技巧点在于利用一个常驻Node
节点作为head
,简化代码。基础的数据结构没事可以看看,磨磨脑子。其实开源库中代码的XList
也是宏定义,没啥亮点,为了提高可读性,直接使用 C++的class
实现。
XList 构造和析构
XList::XList() {
head_ = x_new(Node); // 常驻头结点
head_->next = head_;
head_->prev = head_;
size_ = 0; // 链表初始大小
}
XList::~XList() {
x_delete(head_);
head_ = nullptr;
}
XList 头插和尾插
void XList::PushFront(Node *node) {
node->prev = head_;
node->next = head_->next;
head_->next->prev = node;
head_->next = node;
++size_;
}
void XList::PushBack(Node *node) {
node->prev = head_->prev;
node->next