我有一个看起来像这样的结构:
struct TreeNode
{
int value;
std::unique_ptr<TreeNode> left = nullptr, right = nullptr;
};
我想最好使用unique_ptr
而不是shared_ptr
来实现这样的树实现,对吗?
然后我在priority_queue
中添加了几个节点,例如:
bool operator<(const TreeNode& t1, const TreeNode& t2)
{
return t1.value < t2.value;
}
...
std::priority_queue<TreeNode> nodes;
for(int i = 0; i < 10; i++)
{
TreeNode node;
node.value = i;
nodes.push(node);
}
之后,unique_ptr
遇到问题时,我必须做这样的事情:
TreeNode n1 = nodes.top();
nodes.pop();
TreeNode n2 = nodes.top();
nodes.pop();
TreeNode node;
node.value = n1.value * n2.value;
node.left = std::unique_ptr<TreeNode>(new TreeNode(n1));
node.right = std::unique_ptr<TreeNode>(new TreeNode(n2));
这段代码显然不起作用,但我想知道如何让它尽可能简单地工作。
我设法用我从互联网上获得的make_unique
实现做了一些事情,但它过于临时。我也尝试使用std::move
和std::forward
,但没有成功。
此外,我必须稍后做这样的事情:
std::unique_ptr<TreeNode> root(new HuffmanTreeNode(my_root));
std::unique_ptr<TreeNode> current_node = node;
while(current_node)
{
current_node = current_node->left;
}
在这里,它显然不起作用,但我不知道如何使其正常工作。 (算法也是无稽之谈,只是为了解释我的问题)
你能给我一个例子,告诉我如何在这里完成吗?也许有某种方法可以将unique_ptr
转换为shared_ptr
然后进行反向操作?
答案 0 :(得分:2)
TreeNode
没有复制构造函数(因为隐式构造函数不正确,因为left
和right
不可复制)但它确实有一个隐式移动构造函数,它会将left
和right
移动到新对象中。您有几个地方可以尝试复制:
std::priority_queue<TreeNode> nodes;
for(int i = 0; i < 10; i++)
{
TreeNode node;
node.value = i;
nodes.push(node); // Attempts copy of node
}
// ...
TreeNode n1 = nodes.top(); // Attempts copy of nodes.top()
nodes.pop();
TreeNode n2 = nodes.top(); // Attempts copy of nodes.top()
nodes.pop();
TreeNode node;
node.value = n1.value * n2.value;
// The following two lines attempt to copy n1 and n2, respectively.
node.left = std::unique_ptr<TreeNode>(new TreeNode(n1));
node.right = std::unique_ptr<TreeNode>(new TreeNode(n2));
以下代码中还有其他一些地方,但您明白了。
请注意,您可以std::move()
自己的节点来解决错误:
std::priority_queue<TreeNode> nodes;
for(int i = 0; i < 10; i++)
{
TreeNode node;
node.value = i;
// Use emplace to directly-construct the element in the queue.
nodes.emplace(std::move(node));
}
// ...
// priority_queue<T>::top() gives us a const reference; we have to cast
// the const-ness away (which is legal in this case) to move from it.
// See http://stackoverflow.com/a/20149745/501250
TreeNode n1{std::move(const_cast<TreeNode &>(nodes.top()))};
nodes.pop();
TreeNode n2{std::move(const_cast<TreeNode &>(nodes.top()))};
nodes.pop();
TreeNode node;
node.value = n1.value * n2.value;
node.left = std::unique_ptr<TreeNode>(new TreeNode(std::move(n1)));
node.right = std::unique_ptr<TreeNode>(new TreeNode(std::move(n2)));