[英]Using smart pointers for C++ binary search tree
I have implemented a binary search tree in c++. 我用c ++实现了二叉搜索树。 Instead of using bare pointers to point to a nodes children I used the std::shared_ptr
. 我没有使用裸指针指向节点子节点,而是使用了std::shared_ptr
。 The nodes of the tree are implemented as follows 树的节点如下实现
struct treeNode;
typedef std::shared_ptr<treeNode> pTreeNode;
struct treeNode {
T key;
pTreeNode left;
pTreeNode right;
treeNode(T key) : key(key), left(nullptr), right(nullptr) {}
};
When removing a node from the BST, one of the cases is when the node has only one child. 从BST中删除节点时,其中一种情况是节点只有一个子节点。 The node is simply replaced by this child as shown below: 该子节点简单地替换该节点,如下所示:
| remove node
node ---------> |
\ right
right
In an similar Java implementation this can be coded as: 在类似的Java实现中,这可以编码为:
node = node.getRight();
In my C++ implementation it is: 在我的C ++实现中,它是:
node = node->right;
where node is of type pTreeNode
. 其中node是pTreeNode
类型。
When calling the = operator on an pTreeNode
( std::shared_ptr<TreeNode>
), node
's destructor will be called. 在pTreeNode
( std::shared_ptr<TreeNode>
)上调用=运算符时,将调用node
的析构函数。 The number of shared pointers pointing to the underlying TreeNode
is 1, hence the TreeNode
is destroyed freeing its memory. 指向底层TreeNode
的共享指针的数量为1,因此TreeNode
被销毁以释放其内存。 When the TreeNode
(default) destructor is called, each of its members are destroyed. 当调用TreeNode
(默认)析构函数时,会销毁其每个成员。 This surely would result in the pTreeNode right
member being destroyed. 这肯定会导致pTreeNode right
成员被破坏。 The problem is that node->right
is what is being assigned to node
. 问题是node->right
是分配给node
。 When testing my BST, it appears to work fine with no errors/memory leaks. 在测试我的BST时,它似乎工作正常,没有错误/内存泄漏。
A 'hack' that i figured may work would be to make another pointer to increase its reference count. 我认为可能有用的“黑客”是制作另一个指针以增加其引用计数。 Would this be an adequate solution? 这是一个适当的解决方案吗?
//increase reference to node->right by 1 so it doesn't get destroyed
pTreeNode temp(node->right);
node = node->right;
You are apparently assuming that, in 你显然是假设,在
node = right;
shared_ptr
's assignment operator may decrement node's count before having finished reading from right
(or before incrementing the ref count used by right
). shared_ptr
的赋值运算符可以在从right
读取之前(或在增加right
使用的引用计数之前)减少节点的计数。 However, according to cppreference, using 但是,根据cppreference,使用
template<typename T>
template<typename U>
std::shared_ptr<T> &std::shared_ptr<T>::operator =(const std::shared_ptr<U> &);
as 如
node = right; // std::shared_ptr<treeNode>
is equivalent to 相当于
std::shared_ptr<treeNode>(right).swap(node);
which is safe because right
is copied before the old value of node
is destroyed. 这是安全的,因为在销毁旧的node
值之前复制了right
。 As an aside, I have implemented a shared pointer myself and I saw to it that "cleaning up" the old value is the last thing I do inside of operator =
precisely to avoid such problems. 顺便说一句,我自己实现了一个共享指针,我看到它“清理”旧值是我在operator =
做的最后一件事operator =
正是为了避免这些问题。
- Is what I am doing unsafe? 我在做什么不安全?
No, it's safe as far I can see. 不,我能看到它是安全的。 The left
or right
node instances will be kept alive until their ref count falls to zero. left
或right
节点实例将保持活动状态,直到它们的引用计数降至零。
- If it is unsafe, what could I do to get around this problem? 如果它不安全,我该怎么做才能解决这个问题?
The only relevant thing you should be aware of is not to hand out any nodes as shared_ptr
's outside of the tree implementation. 您应该注意的唯一相关事项是不要将任何节点shared_ptr
为shared_ptr
在树实现之外。 These should be std::weak_ptr
's or raw pointers. 这些应该是std::weak_ptr
或原始指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.