【发布时间】:2020-03-01 17:42:57
【问题描述】:
我正在尝试使用智能指针构建二叉树,其中节点还包括父指针。为此,我将子指针定义为shared_ptr,将父指针定义为weak_ptr。
我能想到的最好的方法如下:
#include <iostream>
#include <memory>
using namespace std;
struct Node;
struct NodeBase {
int val;
NodeBase(int v) : val(v) {}
virtual void add_node_left(shared_ptr<Node> &ptr, int v) = 0;
virtual void add_node_right(shared_ptr<Node> &ptr, int v) = 0;
virtual ~NodeBase() {};
};
struct NodePtr {
shared_ptr<NodeBase> ptr;
template<typename... Args>
NodePtr(Args&&... args) : ptr(std::forward<Args>(args)...) {}
void add_left(int v) {
shared_ptr<Node> node_ptr = std::static_pointer_cast<Node>(ptr);
ptr->add_node_left(node_ptr, v);
}
void add_right(int v) {
shared_ptr<Node> node_ptr = std::static_pointer_cast<Node>(ptr);
ptr->add_node_right(node_ptr, v);
}
};
struct Node : public NodeBase {
NodePtr left, right;
weak_ptr<Node> parent;
Node(int v) : NodeBase(v), left(nullptr), right(nullptr), parent() {}
shared_ptr<Node> make_child(shared_ptr<Node> &selfptr, int v) {
auto child = make_shared<Node>(v);
child->parent = selfptr;
return child;
}
void virtual add_node_left(shared_ptr<Node> &selfptr, int v) {
left = make_child(selfptr, v);
}
void virtual add_node_right(shared_ptr<Node> &selfptr, int v) {
right = make_child(selfptr, v);
}
virtual ~Node() {};
};
struct Tree {
NodePtr root;
Tree() : root(nullptr) {};
Tree(int val) {
add_root(val);
}
void add_root(int val) {
root = make_shared<Node>(val);
}
};
int main() {
Tree tree;
tree.add_root(10);
tree.root.add_left(5);
tree.root.add_right(12);
}
首先,这是正确的吗?
其次,我不太喜欢定义NodeBase 基类。这样做的原因是我可以将shared_ptr 传递给add_node_left 和add_node_right,这是创建父weak_ptr 所需的。有没有办法避免NodeBase 但保持相同(或相似)的界面?
【问题讨论】:
-
root 应该是
unique_ptr,每个节点的子节点也应该是。其他一切都应该是一个普通的指针。这样做的好处是,一旦你修剪了一个孩子,以该孩子为根的子树将自动释放,尽管有一个警告。查看this 链接了解更多信息。
标签: c++ smart-pointers