Rer*_*ito 2 c++ oop constructor
我目前正在为搜索树等经典数据结构编写实现.我从B +树开始.
涉及的课程如下:
template <typename Key, typename Record>
class BPlusNode {
/* ... */
}
template <typename Key, typename Record>
class BPlusINode : public BPlusNode<Key, Record> {
/* ... */
}
template <typename Key, typename Record>
class BPlusLeaf : public BPlusNode<Key, Record> {
/* ... */
}
template <typename Key, typename Record>
class BPlusTree {
/* ... */
private:
BPlusNode<Key, Record> *root;
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
我正在为我的树编写复制构造函数.它有点复杂,因为它涉及原始树上的BFS搜索,逐个复制每个节点(并相应地编辑子节点和父节点).在复制过程中的某个时刻可能发生内存分配失败(或其他任何错误).因此,我必须抛出异常来表示对象创建失败.但是我创建的所有节点会发生什么?它们会被自动销毁还是我必须清理这些烂摊子?
编辑:关于复制构造函数的一些精度
template <typename Key, typename Record>
BPlusTree<Key, Record>::BPlusTree(BPlusTree<Key, Record> &tree) {
std::list<BPlusNode<Key, Record>*> to_cpy;
BPlusNode<Key, Record> *n = nullptr, *p = nullptr, *cpy = nullptr;
to_cpy.push_back(tree.root);
while (!to_cpy.empty()) {
n = to_cpy.front();
n.listChildren(to_cpy) // Push all @n's children at the back of @to_cpy
// (In order)
to_cpy.pop_front();
cpy = n.clone(); // May fail.
/*
* Some mechanisms to track who is the parent node for @cpy
* and to edit the children pointers when all have been copied
*/
}
}
Run Code Online (Sandbox Code Playgroud)
额外的问题:我将根保持为指针,因为当树进化时,由于B +树不会从上到下而是从下到上生长,因此根可以改变.这是正确的解决方案吗?(右边,我的意思是最多的C++ - esque)
如果构造函数失败,则调用所有完全构造的子对象的析构函数,但不调用构造函数失败的对象的析构函数.
处理此问题的经典方法(std::vector例如,我所见过的所有实现都使用它)将内存管理放在私有基类中,如:
class TreeBase
{
Note* root;
friend class Tree;
TreeBase() : root( nullptr ) {}
~TreeBase() { delete root; } // Or whatever is needed for cleanup.
};
Run Code Online (Sandbox Code Playgroud)
由于在输入树的实际构造函数代码之前将完全构造此基类,因此将调用其析构函数.
root只要可通过的结构root足够连贯以便进行适当的清理,改变就没有问题.甚至可以在短时间内释放此约束,在此期间您可以确保不会引发异常.(例如,重新平衡树时;该操作仅涉及指针操作,它永远不会引发异常.)