【问题标题】:c++ initializing a binary tree nodec++初始化二叉树节点
【发布时间】:2021-07-29 11:25:18
【问题描述】:

我收到以下错误:e0289 no instance of constructor...matches argument list and c2440: 'initializing' cannot convert from initializer list to BinaryTreeNod

我试图将头指向左右子树。


#include <memory>

using namespace std;

template <typename T>
struct BinaryTreeNode{
  T data;
  unique_ptr<BinaryTreeNode<T>> left, right;

  explicit BinaryTreeNode(const T& data) : data(data) {}
  BinaryTreeNode(T data, unique_ptr<BinaryTreeNode<T>> left,
  unique_ptr<BinaryTreeNode<T>> right) : data(data), left(move(left)),
  right(move(right)) {}
};

int main()
{

  BinaryTreeNode<int> subtree_0{ 5 };
  BinaryTreeNode<int> subtree_1{ 7 };
  BinaryTreeNode<int> head{3, subtree_0, subtree_1 };
}

错误来自 BinaryTreeNode head{3, subtree_0, subtree_1 }; 行。构造函数有问题吗?或者我在尝试这样初始化时做错了什么? 只是想制作一个简单的二叉树(BinaryTree节点的代码来自《编程面试要素》

【问题讨论】:

  • 你试过BinaryTreeNode&lt;int&gt; head{3, &amp;subtree_0, &amp;subtree_1 };吗?不过,std::unique_ptr 想要获得所有权(以及delete 超出范围时的实例)。这对局部变量来说是个坏主意。
  • 在这种情况下,一种可能的解决方法是使用new 创建实例subtree_0subtree_1 并将它们存储为原始指针。你也可以考虑std::make_unique,但你也必须在通话中移动它们。
  • Scheff 是的,我做了,不起作用。
  • 是的,我做了,但不起作用。 可能没有从原始指针到 std::unique_ptr 的隐式转换。 (必须查看文档...)是的。很明确:std::unique_ptr::unique_ptr。 (这是(3​​)。)
  • 我曾经用std::unique_ptrs 制作了一个示例来处理可以传递实例和临时对象的事情。 (它使用std::unique_ptr 的删除器选项来实现这一点。)Demo on coliru。它可以很好地使用,但需要付出一些努力......此外,在我的生产性工作中,我当然有派生类。由于获得临时的所有权需要一个副本,因此我必须添加一个“虚拟副本构造函数”又名。指向指针类的virtual 克隆方法。

标签: c++ tree binary


【解决方案1】:

std::unique_ptr 不支持隐式指针到唯一指针的转换,但它有一个显式构造函数来执行此操作。但是不建议为它分配一个堆栈分配的指针,因为它可能稍后会尝试删除它。

为了解决这个问题,我们需要用唯一的指针来制作这两个节点。

std::unique_ptr<BinaryTreeNode<int>> subtree_0 = std::make_unique<BinaryTreeNode<int>>(BinaryTreeNode<int>(5));
std::unique_ptr<BinaryTreeNode<int>> subtree_1 = std::make_unique<BinaryTreeNode<int>>(BinaryTreeNode<int>(7));

但正如规范所述,您不能复制任何唯一指针。这意味着我们需要将这两个指针移动到树节点对象。为此,我们需要在构造函数中将它们作为rvalues 接受。然后我们可以毫无问题地移动指向对象的指针。

template <typename T>
struct BinaryTreeNode {
    ...
    BinaryTreeNode(T data, std::unique_ptr<BinaryTreeNode<T>>&& left,
        std::unique_ptr<BinaryTreeNode<T>>&& right) : data(data), left(std::move(left)), right(std::move(right)) {}
};

int main()
{
    std::unique_ptr<BinaryTreeNode<int>> subtree_0 = std::make_unique<BinaryTreeNode<int>>(BinaryTreeNode<int>(5));
    std::unique_ptr<BinaryTreeNode<int>> subtree_1 = std::make_unique<BinaryTreeNode<int>>(BinaryTreeNode<int>(7));
    BinaryTreeNode<int> head{ 3, std::move(subtree_0), std::move(subtree_1) };
}

【讨论】:

  • 非常感谢!我根本不知道这种用 make shared 初始化的方式,而且,使它成为右值 && 对我来说是一个相对较新的概念。它确实修复了错误,但是,现在我收到一个新错误: C2280 std::unique_ptr,std::default_delete>>::unique_ptr(const std::unique_ptr >,std::default_delete>> &)': 试图引用已删除的函数
  • @kanulilewa 你确定你使用std::move移动指针吗?
  • 阳性。刚刚将代码从这里复制并粘贴到我的程序中。
  • 好的,找到了,抱歉我不小心从构造函数中删除了“移动”
  • 再次感谢 D-Raj 和 Scheff - 您的帮助是无价的!​​span>
猜你喜欢
  • 2016-01-22
  • 1970-01-01
  • 2020-08-19
  • 1970-01-01
  • 2014-03-07
  • 2013-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多