【发布时间】:2022-01-07 15:13:43
【问题描述】:
我正在实现一个双向链表,它以哨兵节点为头和尾,比如这个名为List 的类。 Node 是 List 中的私有结构。该类有一个私有方法Init用于初始化头尾节点,在List的构造函数中调用。
template<typename T>
class List {
public:
List() {
Init();
}
...
private:
struct Node {
T data;
Node* prev;
Node* next;
// Constructors
};
size_t size;
Node* head;
Node* tail;
void Init() {
// Codes arise some problem if instances of T have no default constructor.
head = new Node;
tail = new Node;
head->prev = nullptr;
head->next = tail;
tail->prev = head;
tail->next = nullptr;
size = 0;
}
};
现在的问题是,如果T 的实例没有默认构造函数,我无法使用head = new Node; 和tail = new Node; 创建哨兵节点。 new 运算符总是分配一块内存并构造它。在构造Node对象时,必须使用T的一些构造函数来初始化Node中的data字段。
有没有办法检查T 的哪些构造函数(除了复制和移动构造函数)我可以用来构造T 类型的变量data?或者我可以只初始化Node 中的prev 和next 字段,而使data 字段未初始化?
【问题讨论】:
-
如果
T没有默认构造函数,那么你会得到一个编译时错误。 -
即使你知道它有什么构造函数,这对你有什么帮助?假设您发现有
T(X, int, int, bool, Y, Z)构造函数。你会用这些信息做什么?它实际上是没有用的。请记住,您处于通用上下文中。正确的做法是:永远不要初始化T对象,除非您的 api 用户明确请求它。你不知道T是什么。也许即使它有一个默认构造函数,它也是一个非常昂贵的操作。 -
Init()是否打算创建一个包含0元素的List?如果是这种情况,您可能希望Init()的设计也创建零Ts。 -
struct Node { virtual ~Node() = default; Node* prev; Node* next; }; struct DataNode : Node { T data; }; -
你不需要为
head和tail动态分配节点来指向,它们和拥有的List具有相同的生命周期
标签: c++ algorithm data-structures linked-list doubly-linked-list