c++ - 在指针场景中使用 std::shared_ptr

标签 c++ shared-ptr c++17 smart-pointers

我创建了一个 Node用于二叉搜索树实现的结构。它使用共享指针来跟踪它的 child :

template <class T> struct Node;

template <class T>
using Node_ptr = std::shared_ptr<Node<T>>;

template <class T>
struct Node {
  Node_ptr<T> left;
  Node_ptr<T> right;
  const T label;
  ...
};

现在,我想要一个函数,它给定一些子树和一个值,该函数将返回该特定值的节点或该节点将来应该位于的位置 - find_node .

现在是这样的:

template <class T>
auto* find_node(Node_ptr<T>* node, const T& value) {
  for (; *node && (*node)->label != value
       ; node = value < (*node)->label ? &(*node)->left : &(*node)->right);

  return node;
}

很糟糕。但它有效:

template <class T>
class Binary_search_tree {
public:
  // correctly inserts consecutive values
  void insert(const T& value) {
    if (auto* node = find_node(&root, value); !*node)
      *node = std::make_shared<Node<T>>(value);
  }
  ...
private:
  Node_ptr<T> root;
  ...
};

我可以重写 find_node使用 std::shared_ptr<Node_ptr<T>>而不是 Node_ptr<T>*但它看起来会更糟。还是会?

我应该如何处理这种情况?

编辑:正如已经指出的那样,可以通过引用起始节点并返回对节点的引用来稍微简化该函数:

template <class T>
Node_ptr<T>& find_node(Node_ptr<T>& node_ref, const T& value) {
  auto* node = &node_ref;
  ...
  return *node;
}

最佳答案

  1. 当您必须允许传递空指针时,建议使用原始指针——在您的示例中并非如此;或者当您必须传递一个非整数值时(在您的情况下为真)。在后一种情况下,仍应考虑传递引用而不是原始指针。这是一般性建议 - 因此可能存在异常(exception)情况。

  2. 注意到,通过将 find_node(...) 设为私有(private)函数同时保持 insert(...) 公开,您仍然可以在这里相当安全地在函数中使用原始指针。这是安全的,因为不可能让指针在 insert(...) 内部悬空。

本质上,我们需要防止使用原始指针的两种可能性:#1。过早删除指针指向的内存,#2。永远不要删除指针指向的内存。这在您的 insert(...) 函数中都是不可能的。所以你很安全。

在相关说明中,您可能会考虑在创建节点时为节点设置 unique_pointer,然后如果要由多个子节点共享它们,则将它们转换为共享指针:std::move(...)。

关于c++ - 在指针场景中使用 std::shared_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51643548/

相关文章:

c++ - 将一个元组重新映射到另一个元组

c++ - 将 `std::string` 临时值传递给 `std::string_view` 参数是否安全?

c++ - 是否可以根据调用站点的上下文指定不同的 C++ `operator==` 功能?

c++ - 在 C++ 中如何更改存储在字符串中的文件扩展名?

multithreading - C++11共享指针线程安全被破坏?

c++ - 传递给父类(super class)的构造函数时的临时 boost::shared_ptr

c++ - 将 make_shared 与不完整的类型一起使用

c++ - 使用 C++ std::regex_replace 匹配不同数量的行

c++ - 我很难调试较长的编译时间和多个用户输入要求

c++ - 处理标准一维数组时忽略前导空格