【发布时间】:2017-08-14 20:01:59
【问题描述】:
在尝试使用 C++11 创建二叉搜索树 (BST) 时遇到了障碍。 我无法从创建它的函数中提取正确创建的 BST。 该函数从文件中读取数据(在这种情况下,每行只有一个数字)并从中构建 BST。循环中的构建部分正常工作。 问题是我无法将临时对象移动到我想要的位置。
放大我认为的问题,请参阅编辑 3。
更多上下文:
BST<T> 是一个公开派生自 std::unique_ptr<BSTknoop<T>> 的类BST<T> 还继承了 unique_ptr<BSTknoop<T>> 的构造函数与
template<class T>
using BSTknoopptr=std::unique_ptr<BSTknoop<T>>; // alias template
和
using BSTknoopptr<T>::BSTknoopptr; // in the body of the BST<T> class declaration`
BSTknoop<T> 是一个包含 3 个字段的数据结构
一个 T 对象来保存节点数据
左右两个BST<T>对象(每个孩子都是一棵树)
目标是将我新创建的 BST 移动到调用对象中。这个想法是,在 main 中,您可以调用 BST<int> tree; tree.lees(ifs);(ifs 是一个打开的输入文件流),然后 tree 保存正确填充的 BST。
功能:
template<class T>
istream& BST<T>::lees(istream& is){
string lijn;
T knoopwaarde;
getline(is,lijn);
knoopwaarde = stoi(lijn);
BST<T> temptree(new BSTknoop<T>());
temptree->sl = knoopwaarde;
for(int i=1; i<DATA_SET_LENGTH ; i++){
getline(is,lijn);
knoopwaarde=stoi(lijn);
temptree.add(knoopwaarde);
cout<<temptree;
}
this->swap(temptree); /* This does not work */
/* *this = move(temptree); this does not work either*/
return is;
}
我还尝试从函数中返回 BST<T> 并将该结果移动到主函数中。那也没用。
程序在运行时因未知信号而崩溃。
旁注:我不确定为什么BST<T> temptree(new BSTknoop<T>()); 在模板方面起作用。构造工作是因为BST<T> 继承了unique_ptr<BSTknoop<T>> 的构造函数
编辑 1:BST<T> 类的声明:
template <class T>
class BST:public BSTknoopptr<T>{
using BSTknoopptr<T>::BSTknoopptr;
public:
friend istream& operator>>(istream& is, BST<T>& bb){
return bb.lees(is);
}
friend ostream& operator<<(ostream& os, const BST<T>& bb){
//return bb.schrijflevelorder(os);
return bb.schrijfKnoop(os);
}
void add(const T&);
ostream& schrijf(ostream&);
ostream& schrijfKnoop(ostream&) const;
int aantalSleutels() const;
istream& lees(istream&);
ostream& schrijflevelorder(ostream& os) const;
private:
};
BSTknoop<T> 类的声明:
template <class T>
class BSTknoop{
friend class BST<T>;
public:
BSTknoop() {}
explicit BSTknoop(T _sl) : sl(_sl) {}
private:
T sl;
BST<T> links,rechts;
};
编辑 2:我编写了一个移动构造函数和移动赋值运算符。我已确保使用BST<T>()=default; 保留默认构造函数,但我很困惑:BST 类没有任何成员,我必须为其实现自己的 move constr / 运算符。
但是,BST 隐式继承自unique_ptr<BSTknoop<T>>,因此它必须拥有该类型的成员。假设我想保留继承,有没有什么巧妙的方法可以使这项工作?
我不能(或者可能不应该)实现一个复制constr / 操作符,因为那些是为unique_ptr 删除的,这也是真的吗?
template<class T>
BST<T>::BST(BST<T>&& other){
*this = move(other);
}
template<class T>
BST<T>& BST<T>::operator=(BST<T>&& other){
cout<<"called move operator BST"<<endl;
(*this).BSTknoopptr<T>::operator=(move(other));
return *this;
}
编辑 3:使用我自己的 move constr / 运算符,临时树不再被正确填充。下面是我用于构建树的 add 代码。如果我省略了我自己的 move constr / 运算符,那么这是可行的。我需要的是一个类似于this->get()->links = move(tmp) 的操作。
类型this->get()->links => BST<T>
tmp => BST<T>
这怎么行?它做了我需要的操作,为什么我不能通过自己编写操作来使用类似的东西来做*this = move(temptree)。
template<class T>
void BST<T>::add(const T& value){
if(value <= this->get()->sl){
if(this->get()->links != nullptr){
this->get()->links.add(value);
}
else {
BST<T> tmp(new BSTknoop<T>(value));
this->get()->links = move(tmp);
}
}
else{
if(this->get()->rechts != nullptr){
this->get()->rechts.add(value);
}
else{
BST<T> tmp(new BSTknoop<T>(value));
this->get()->rechts = move(tmp);
}
}
}
【问题讨论】:
-
显示
swap(BST&)和operator=(BST&&)成员的实现以及BST模板类的定义会很有帮助。我们无法调试我们看不到的代码。 -
顺便说一句,我想说你可能不应该从
unique_ptr<>继承。相反,BST<T>应该有一个 成员,该成员是unique_ptr<>。 -
当你决定继承
std::unique_ptr时,我担心你开始陷入混乱。那就是疯狂。 -
@molbdnilo 我认为这被夸大了。如果出于特定目的这样做,这可能很好。从
unique_ptr继承是迄今为止实现某些其他智能指针的最快方式。例如。一个智能指针,它只是在复制时对指针进行深度复制。 -
@cdhowie 他们以前不在那里,我没有实现它们。我依靠继承的/默认生成的,这可能是一个错误。但是,就目前而言,它仍然无法正常工作。
标签: c++ c++11 move-semantics unique-ptr