为什么此代码不能用于删除链表中的节点?

时间:2015-10-03 22:59:51

标签: c++ pointers linked-list delete-operator

我一直在学习链接列表的工作方式,并开始在C ++中构建实现以强化概念。直到我创建一个删除所有节点的功能之后,它一直很顺利。我想出了一个解决方案(这是注释代码),但我似乎无法弄清楚为什么其他代码不起作用。

Node对象是使用“new”创建的类的实例。因此,'删除'用于删除它。

我认为这可能与删除对象和重用指针变量有关。然后我遇到了这个:What happens to a pointer itself after delete? 我一直在盯着它试图找出它可能是什么,而我所研究的任何东西似乎都没有提供答案。

到目前为止,我不相信它是我的实现的东西,因为当用解决方案代码替换代码时,程序按预期工作。

代码输出每个地址,但它似乎没有实际删除对象。如果我在Windows中运行该程序,该程序将实际锁定并永远不会离开while循环。它不是一个无限循环,它只是卡住而且函数永远不会完成。如果我在C4Droid上运行它,程序不会锁定,但在函数退出后节点仍然存在。

所以我的问题是,为什么当前的代码不起作用? (忽略注释的代码。这是一个有效的解决方案。)有什么简单的我用指针变量忽略了吗?先感谢您。

void LinkedList::deleteAll() {
Node *pCurrent = pHead;

while(pCurrent){
    Node *pNext = pCurrent->pNext;
    std::cout << pCurrent << std::endl;
    delete pCurrent;
    pCurrent = nullptr;
    pCurrent = pNext;

//  pHead = pHead->pNext;
//  delete pCurrent;
//  pCurrent = pHead;
}
}

节点类

class  Node{
    public:
        Node(string content):data(content){}
        string getData(){
            return data;
        }
        Node *pNext = nullptr;
    private:
        string data;
    };

LinkedList.h

/*
 * LinkedList.h
 *
 *  Created on: Oct 3, 2015
 *      Author: Anthony
 */

#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_

#include<string>
using std::string;

class LinkedList {
public:
    LinkedList();
    virtual ~LinkedList();
    int length();
    void addNode(string nodeContent);
    void deleteNode(string nodeContent);
    void deleteAll();
private:
    class  Node{
    public:
        Node(string content):data(content){}
        string getData(){
            return data;
        }
        Node *pNext = nullptr;
    private:
        string data;
    };

    Node *pHead = nullptr;

};

#endif /* LINKEDLIST_H_ */

LinkedList.cpp

    /*
 * LinkedList.cpp
 *
 *  Created on: Oct 3, 2015
 *      Author: Anthony
 */

#include "LinkedList.h"
#include <iostream>
LinkedList::LinkedList() {
    // TODO Auto-generated constructor stub

}

LinkedList::~LinkedList() {
    // TODO Auto-generated destructor stub
}

int LinkedList::length() {
    Node *current = pHead;
    int count = 0;
    while(current){
        count++;
        current = current->pNext;
    }
    return count;
}

void LinkedList::addNode(std::string nodeContent) {
    Node *newNode = new Node(nodeContent);
    newNode->pNext = pHead;
    pHead = newNode;
}

void LinkedList::deleteNode(std::string nodeContent) {
}

void LinkedList::deleteAll() {
    Node *pCurrent = pHead;

    while(pCurrent){
        Node *pNext = pCurrent->pNext;
        std::cout << pCurrent->pNext << std::endl;
        delete pCurrent;
        pCurrent = nullptr;
        pCurrent = pNext;

    //  pHead = pHead->pNext;
    //  delete pCurrent;
    //  pCurrent = pHead;
    }
}

的main.cpp

/*
 * main.cpp
 *
 *  Created on: Oct 3, 2015
 *      Author: Anthony
 */

#include<iostream>
#include "LinkedList.h"

int main(int argc, char **argv){

    using namespace std;

    LinkedList list = LinkedList();
    list.addNode(string("Test"));
    list.addNode(string("Test1"));

    list.deleteAll();
    cout << list.length() << endl;

    return 0;
}

2 个答案:

答案 0 :(得分:3)

假设(并且这是一个很大的假设)您的链接列表正确组合在一起,注释代码工作原因和新代码的问题相当简单。

  pHead = pHead->pNext;
  delete pCurrent;
  pCurrent = pHead;

在上面的代码中,当您循环时,您正在将pHead指针移动到列表中。循环结束后,pHead指针为nullptr,这是正确的,因为列表现在为空。

Node *pNext = pCurrent->pNext;
    std::cout << pCurrent << std::endl;
    delete pCurrent;
    pCurrent = nullptr;
    pCurrent = pNext;

使用新的未注释代码,在循环结束后没有设置pHead指针,从而使其指向垃圾。之后对链表的任何使用都将失效。

因此,该功能并不是删除所有节点,而是在删除了节点之后,链表有一个狂野的pHead指针,并且在任何后续功能中使用链接列表的pHead节点变得不稳定。

尝试以下方法:

void LinkedList::deleteAll() {
Node *pCurrent = pHead;
while(pCurrent){
    Node *pNext = pCurrent->pNext;
    delete pCurrent;
    pCurrent = nullptr;
    pCurrent = pNext;
}
pHead = nullptr;  // Sets the head pointer to nullptr, denoting that the list is empty.

答案 1 :(得分:2)

使用&#34; new&#34;创建对象时,涉及两个主要的内存区域。关键字,&#34;调用堆栈,&#34;它跟踪局部变量和已调用的函数,以及&#34;堆,&#34;它旨在以牺牲速度为代价来保存大量数据。

当你声明局部变量pCurrent时,会在&#34;调用堆栈上创建一个指针,&#34;就像一个局部整数变量将被放在堆栈上,声明&#34; int a;&#34;不需要删除堆栈上的局部变量和变量。

使用&#34; new&#34;创建的所有对象但是,需要删除它们,因为它们是在堆上创建的。

正如PaulMcKenzie所写,请务必将头指针设置为null。

void LinkedList::deleteAll() {

    Node *pCurrent = pHead;

    while(pCurrent){
        Node *pNext = pCurrent->pNext;
        std::cout << pCurrent << std::end;
        delete pCurrent;

        pCurrent = pNext;
    }

    pHead = nullptr;
}