解决了!见下文
所以,我试图通过做一些简单的数据结构并玩弄它们来学习 C++11。我使用原始指针做了类似于以下 BST 示例的操作new
,并且delete
效果很好。然后我想以一种更安全的方式来做这件事。
// tree.cpp
//
//
#include <iostream>
#include <memory>
/* DECLARATIONS */
template <typename T>
struct Tree {
// members
T data;
std::unique_ptr<Tree<T> > left;
std::unique_ptr<Tree<T> > right;
// methods
Tree (T arg);
~Tree () = default;
void insert (Tree<T> child);
void insert (T arg);
void print (void);
};
template <typename T>
Tree<T>::Tree (T arg) {
data = arg;
left = nullptr;
right = nullptr;
}
template <typename T>
void Tree<T>::insert (Tree<T> child) {
if (child.data < data) {
if (left) {
left->insert(child);
} else {
left = &child;
}
} else {
if (right) {
right->insert(child);
} else {
right = &child;
}
}
}
template <typename T>
void Tree<T>::insert (T arg) {
Tree<T> child (arg);
this->insert(child);
}
template <typename T>
void Tree<T>::print (void) {
if (left) {
left->print();
}
std::cout << data;
if (right) {
right->print();
}
}
int main (void) {
Tree<int> root (0);
root.insert(3);
root.insert(-3);
root.insert(-2);
root.insert(2);
root.insert(11);
root.print();
return 0;
}
但是,我并不了解我从 clang++ 得到的错误。
$ clang++ -std=c++11 tree.cpp
tree_new.cpp:50:16: error: call to deleted constructor of 'Tree<int>'
this->insert(child);
^~~~~
tree_new.cpp:66:8: note: in instantiation of member function 'Tree<int>::insert' requested here
root.insert(3);
^
tree_new.cpp:10:8: note: function has been explicitly marked deleted here
struct Tree {
^
tree_new.cpp:18:24: note: passing argument to parameter 'child' here
void insert (Tree<T> child);
^
tree_new.cpp:34:20: error: call to deleted constructor of 'Tree<int>'
left->insert(child);
^~~~~
tree_new.cpp:50:9: note: in instantiation of member function 'Tree<int>::insert'requested here
this->insert(child);
^
tree_new.cpp:66:8: note: in instantiation of member function 'Tree<int>::insert' requested here
root.insert(3);
^
tree_new.cpp:10:8: note: function has been explicitly marked deleted here
struct Tree {
^
tree_new.cpp:18:24: note: passing argument to parameter 'child' here
void insert (Tree<T> child);
^
2 errors generated.
为什么它说我在声明时明确删除了构造函数struct
?我什至明确定义了一个构造函数!此外,我们将不胜感激有关范围界定/所有权失败的任何评论。我很确定这无论如何都不会像我那样工作。
解决方案
MSDN的以下链接阐明了如何使用unique_ptr
s.
特别感谢 BatchyX 对问题的初步解释(unique_ptr
隐式使用 a 作为成员(尽管编译器说“显式”...)删除了类的复制构造函数),并注意到 Tree 确实仍然是可移动的。
该 MSDN 文章中提到的内容是std::move()
返回其参数的右值。
这是经过适当修改的代码(不包括明显修改的声明)。请注意,使用 std::forward 可能仍然可以进行一些优化,但这至少似乎可以正确编译和运行。
template <typename T>
void Tree<T>::insert (std::unique_ptr<Tree<T> >&& pchild) {
if (pchild->data < data) {
if (left) {
// recurse, but must match on the rvalue signature
left->insert(std::move(pchild));
} else {
// invokes the move constructor for left instead of its copy constructor
left = std::move(pchild);
}
} else {
if (right) {
right->insert(std::move(pchild));
} else {
right = std::move(pchild);
}
}
}
template <typename T>
void Tree<T>::insert (T arg) {
// what is inside the insert(...) is an rvalue.
this->insert(std::unique_ptr<Tree<T> >(new Tree<T> (arg)));
}