简体   繁体   English

使用智能指针进行C ++二叉搜索树

[英]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. pTreeNodestd::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时,它似乎工作正常,没有错误/内存泄漏。

  • Is what I am doing unsafe? 我在做什么不安全?
  • If it is unsafe, what could I do to get around this problem? 如果它不安全,我该怎么做才能解决这个问题?

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. leftright节点实例将保持活动状态,直到它们的引用计数降至零。

  • 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_ptrshared_ptr在树实现之外。 These should be std::weak_ptr 's or raw pointers. 这些应该是std::weak_ptr或原始指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM