C ++:问题在当前实例被破坏后创建类的新实例

时间:2013-01-27 22:18:14

标签: c++ segmentation-fault instance

我正在开发二进制搜索树(BST)程序。根据赋值的要求,用户加载文本文件以构造树。如果用户想要,他们可以通过加载新的文本文件来创建新树。加载新文本文件应该销毁旧树。

为了满足此要求,我创建新树的方法readNewFile()首先检查树是否已存在。如果是,它将在树上运行析构函数。但是,我需要创建一个存在于readNewFile()范围之外的新树,以便可以全局访问它。这可能吗?如果是这样,你能解释一下吗?

我的缩减代码:

int main() {

    //BST
    BST rootTree;

    readNewFile(rootTree);
    readNewFile(rootTree);

    return 0;
}


void readNewFile(BST& tree) {
    ifstream inFile;
    string fileName;

    // if tree was previously filled, destroy it
    if (tree.rootPtr() != NULL) {
        tree.~BST();
        BST tree = new BST();
    }

    cout << "\nEnter file to load: ";
    cin.ignore();
    getline(cin, fileName);
    cout << "Opening file " << fileName << endl;
    inFile.open(fileName.c_str(), ios::in);

    // Populates tree... //

}

析构函数(在BST.hpp中):

BST::~BST() {
    destroyTree(root);
}

void BST::destroyTree(TreeNode*& treePtr) {
    if (treePtr != NULL) {
        destroyTree(treePtr->leftChildPtr);
        destroyTree(treePtr->rightChildPtr);
        delete treePtr;
    }
}

这会返回一个段错误,这是有意义的,因为树被破坏了。但是,有没有办法可以创建一个新树,其范围与被破坏的BST rootTree相同?

3 个答案:

答案 0 :(得分:1)

实现此要求的一种方法是在del()类中使用名为BST的方法。它所做的就是删除树的所有节点,但不删除根指针。这是指向根节点的指针。调用del()后,您可以开始创建新树。伪代码看起来像这样:

// if tree was previously filled, destroy it
if (tree.rootPtr() != NULL) {
   tree.del()
}

// read the input file
// Start inserting the new nodes

答案 1 :(得分:1)

首先:代码出了什么问题。

正如您已经指出的那样,如果树被破坏,您将无法再次使用它。在这种情况下,它是双坏的:通过调用BSTreadNewFile()上的析构函数,你导致析构函数被调用两次 - 一次是在你明确调用它时,第二次是main()中的本地实例超出范围。 This is bad.


现在关于如何解决它:

最简单的方法是将rootTree声明为main()内的指针,然后使readNewFile()将指针指针作为参数。 readNewFile()会破坏指针指向的现有树,然后将指针重置为指向它创建的新树。简单。

更好的设计是使readNewFile()成为BST的成员函数。然后main()应该构建一个新的BST并调用该实例的readNewFile()

答案 2 :(得分:0)

你永远不会直接调用析构函数,除非你很清楚你正在做什么。然后,它通常是因为它是使用placement new创建的。此外,“T t = new T;”没有意义,将指针指向T.我的猜测是你在这里复制Javaism,但这两种语言的对象模型太不同了。