为什么我的二进制搜索树过载的移动赋值运算符不能根据我的代码正确删除?

时间:2018-11-18 01:56:26

标签: c++ tree binary variable-assignment move

BST.cpp的重载移动分配运算符:

BST& BST::operator=(BST&& otherBST) {
    if (this != &otherBST) {
        if (root) {
            stack <Node*> nodeStack;
            nodeStack.push(root);

            Node *currentNode = nullptr;
            while (!nodeStack.empty()) {
                currentNode = nodeStack.top();
                nodeStack.pop();

                if (currentNode->rlink) {
                    nodeStack.push(currentNode->rlink);
                }
                if (currentNode->llink) {
                    nodeStack.push(currentNode->llink);
                }

                delete currentNode;
                currentNode = nullptr;
            }
            cout << root << endl; // This is where it seems like root is not being deleted correctly/nullptr'd.
        }

        root = move(otherBST.root);
        otherBST.root = nullptr;
    }
    else {
        cerr << "ERROR: Cannot assign to self." << endl;
    }

    return *this;
}

看一下我评论过的cout << root << endl部分。当该段代码运行时,它会打印出除00000000以外的地址。这似乎并没有正确删除它们。

这是一个代码,其中删除了调用对象的BST(所有分支),然后窃取了其他BST的树。移动分配运算符。 但是为什么不打印nullptr而是打印另一个地址?似乎它没有被正确删除。

在这里供参考:

这是正在运行的测试驱动程序的屏幕截图:click here to see.

Main.cpp

#include <iostream>
#include "Test.h"
using namespace std;

int main()
{
    runTest();

    cout << endl << endl;
    system("Pause");
    return 0;
}

Test.h

#include "BST.h"

void runTest() {
    cout << "--------------------------------------------------------------------" << endl;
    cout << "Binary Search Tree Test Driver" << endl;
    cout << "--------------------------------------------------------------------" << endl;
    // Initialization:
    BST bst1;
    // Traversal when there are no elements in the tree:
    cout << "BST traversal when there are no elements within the tree (bst1): " << endl;
    bst1.preorderTraversal();
    cout << endl;
    cout << "BST, inserting one element into the tree recursively and non-recursively (bst1): " << endl;
    bst1.insert(21);
    bst1.preorderTraversal();
    cout << endl;
    bst1.insert(69);
    bst1.preorderTraversal();
    cout << endl;
    cout << "BST, inserting duplicate elements into the tree recursively (bst1): " << endl;
    bst1.insert(32);
    bst1.insert(32);
    bst1.preorderTraversal();
    cout << endl;
    cout << "BST using the function destroyTree (bst1): " << endl;
    bst1.destroyTree();
    bst1.preorderTraversal();
    cout << endl;
    cout << "BST copy constructor by copy constructing bst1 (bst2): " << endl;
    bst1.insert(21);
    bst1.insert(69);
    BST bst2(bst1);
    bst2.preorderTraversal();
    cout << endl;
    cout << "BST move constructor by move constructing bst1 (bst3): " << endl;
    BST bst3 = move(bst1);
    bst3.preorderTraversal();
    cout << endl;
    cout << "BST move assignment operator by move assigning bst2 (bst1) when bst1 has no elements in its tree: " << endl;
    bst1.destroyTree();
    bst1 = move(bst2);
    bst1.preorderTraversal();
    cout << endl;
    bst1.destroyTree();
    bst2.destroyTree();
    cout << "BST move assignment operator by move assigning bst2 (bst1) when bst1 already has some elements in its tree: " << endl;
    bst1.insert(21);
    bst1.insert(105);
    bst1.insert(18);
    bst1.insert(16);
    bst1.insert(7);
    bst1.insert(19);
    bst1.insert(109);
    bst1.insert(125);
    bst1.insert(101);
    bst2.insert(691);
    bst1 = move(bst2);
    bst1.preorderTraversal();
    cout << endl;
}

BST.h

#ifndef BST_H
#define BST_H

#include <string>       
#include <iostream>
#include <stack>

using namespace std;

class Node
{
    friend class BST;
public:
    Node() : data(0), rlink(nullptr), llink(nullptr) {}
    ~Node() {}
private:
    int data;
    Node *rlink, *llink;
};

class BST
{
public:
    BST();

    BST(const BST& otherBST); 

    BST(BST&& otherBST); 

    void insert(int item);

    void insertNonRecursive(int item);

    void preorderTraversal() const;

    // BST& operator=(const BST& otherBST); 

    BST& operator=(BST&& otherBST); 

    void destroyTree();

    ~BST();

private:
    Node * root; // Pointer to the root.

    void copyConstructor(const Node *p);

    void insert(Node* &p, Node *newNode);

    void preorderTraversal(const Node *p) const;

    void destroyTree(Node *&p);
};

#endif

BST.cpp

#include "BST.h"

BST::BST() : root(nullptr) {}

BST::BST(const BST& otherBST) {
    copyConstructor(otherBST.root);
}

BST::BST(BST&& otherBST) {
    root = move(otherBST.root);

    otherBST.root = nullptr;
}

void BST::copyConstructor(const Node *p) {
    if (p != nullptr) {
        insert(p->data);
        copyConstructor(p->llink);
        copyConstructor(p->rlink);
    }
}


void BST::insert(int insertItem)
{
    Node  *newNode = new Node;
    newNode->data = insertItem;
    insert(root, newNode);
}

void BST::insert(Node* &p, Node *newNode)
{
    if (p == nullptr)
        p = newNode;
    else if (p->data > newNode->data)
        insert(p->llink, newNode);
    else
        insert(p->rlink, newNode);
}

void BST::insertNonRecursive(int item) {
    if (root == nullptr) {
        root = new Node();
        root->data = item;
    }
    else {
        Node *current = root;
        bool searching = true;

        while (searching) {
            if (item > current->data && current->rlink != nullptr) {
                current = current->rlink;
            }
            else if (item < current->data && current->llink != nullptr) {
                current = current->llink;
            }
            else if (item == current->data) {
                cerr << "The item to insert is already in the list, duplicates are not allowed." << endl;
                searching = false;
            }
            else {
                if (item > current->data) {
                    current->rlink = new Node();
                    current->rlink->data = item;
                }
                else {
                    current->llink = new Node();
                    current->llink->data = item;
                }

                searching = false;
            }
        }
    }
}

void BST::preorderTraversal() const {
    if (root == nullptr)
        cerr << "There is no tree.";
    else
    {
        preorderTraversal(root);
    }
}

void BST::preorderTraversal(const Node *p) const {
    if (p != nullptr) {
        cout << p->data << " ";
        preorderTraversal(p->llink);
        preorderTraversal(p->rlink);
    }
}

BST& BST::operator=(BST&& otherBST) {
    if (this != &otherBST) {
        if (root) {
            stack <Node*> nodeStack;
            nodeStack.push(root);

            Node *currentNode = nullptr;
            while (!nodeStack.empty()) {
                currentNode = nodeStack.top();
                nodeStack.pop();

                if (currentNode->rlink) {
                    nodeStack.push(currentNode->rlink);
                }
                if (currentNode->llink) {
                    nodeStack.push(currentNode->llink);
                }

                delete currentNode;
                currentNode = nullptr;
            }
            cout << root << endl; // This is where it seems like root is not being deleted correctly/nullptr'd.
        }

        root = move(otherBST.root);
        otherBST.root = nullptr;
    }
    else {
        cerr << "ERROR: Cannot assign to self." << endl;
    }

    return *this;
}

void BST::destroyTree(Node* &p)
{
    if (p != nullptr)
    {
        destroyTree(p->llink);
        destroyTree(p->rlink);
        delete p;
        p = nullptr;
    }
}

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

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

1 个答案:

答案 0 :(得分:0)

我认为您提到的行很好,没有泄漏任何内容。只是指针没有分配给NULL。 在下面的示例中,您可能正在期望pA为NULL

int *pA = new int;
int *pB = pA;
delete pB;
pB=NULL;

printf("pA=0x%p, pB=0x%p", pA,pAB);

请注意,即使pA指向的东西(现在是悬空的指针)也没有泄漏。

要获得所需的行为,可以在完成压入堆栈后将根设置为NULL。