傳統鏈表要求節點型別固定。若要存放不同結構 (Struct_A, Struct_B),需為每種型別複製插入/刪除/搜尋函數,違反 DRY 原則。
節點結構僅含 next 指標,資料緊接在節點後配置:
typedef struct ListNode {
struct ListNode* next;
} ListNode;
ListNode* ListAdd(ListNode* head, void* data, size_t dataSize) {
// 分配節點 + 資料 連續記憶體
ListNode* node = (ListNode*)malloc(sizeof(ListNode) + dataSize);
void* dataPtr = (void*)(node + 1); // 節點之後即資料
memcpy(dataPtr, data, dataSize);
node->next = head;
return node; // 新頭節點
}
typedef void (*NodeDestructor)(void* node); // 參數為節點指標
typedef struct ListNode {
NodeDestructor destroy;
struct ListNode* next;
} ListNode;
ListNode* ListAdd(ListNode* head, void* data, size_t dataSize, NodeDestructor dtor) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode) + dataSize);
void* dataPtr = (void*)(node + 1);
memcpy(dataPtr, data, dataSize);
node->destroy = dtor;
node->next = head;
return node;
}
void ListDestroy(ListNode* head) {
while (head) {
ListNode* next = head->next;
if (head->destroy) head->destroy(head); // 釋放資料內部資源
free(head);
head = next;
}
}
// 使用範例:資料含動態分配字串
typedef struct { char* str; } StringData;
void StringDataDestructor(void* node) {
ListNode* n = (ListNode*)node;
StringData* d = (StringData*)(n + 1);
free(d->str);
}
ListNode* head = NULL;
StringData d1 = { strdup("Hello") };
head = ListAdd(head, &d1, sizeof(StringData), StringDataDestructor);
StringData d2 = { strdup("World") };
head = ListAdd(head, &d2, sizeof(StringData), StringDataDestructor);
ListDestroy(head); // 正確釋放所有字串
使用 std::list 或 std::vector (C++17),或自製 type_erased_node:
// 概念示意 (非完整代碼)
class INode {
public:
virtual ~INode() = default;
virtual std::unique_ptr Clone() const = 0;
};
template
class Node : public INode {
T value;
public:
Node(T v) : value(std::move(v)) {}
std::unique_ptr Clone() const override {
return std::make_unique(value);
}
T& Get() { return value; }
};
std::list> list;
list.push_back(std::make_unique>(42));
list.push_back(std::make_unique>("hello"));
// 遍歷需 dynamic_cast 或 Visitor 模式
| 方案 | 語言 | 資源管理 | 型別安全 | 效能 | 複雜度 |
|---|---|---|---|---|---|
| 虛擬節點 | C/C++ | 無 (手動) | 無 (void*) | 極高 | 低 |
| 解構器回呼 | C/C++ | 自動 (回呼) | 無 (void*) | 高 | 中 |
| C++ 型別擦除 | C++11+ | 自動 (RAII) | 高 (編譯期) | 中 (虛函數/any) | 中高 |
| C++ 模板同質容器 | C++ | 自動 | 最高 | 最高 | 低 (單型別) |
std::variant (有限型別集) 或 std::any / 型別擦除基類**。std::list / std::vector**。