如何解析反向链表的"Unhandled exception thrown: read access violation."?

How to resolve "Unhandled exception thrown: read access violation." for reverse linked list?

我正在使用 Visual Studio Community 2019 在 Windows 10 Pro(64 位)上开发反向链表。我想知道如何解决我遇到的错误,如下所示。我在 class List

的成员函数 reverse()while 循环中遇到以下错误

(*请假设列表已经像连续整数一样准备好,例如 0,1,2,3,4,5) 你能请任何人给我一些建议吗?提前谢谢你。

抛出未处理的异常:读取访问冲突。 当前 是 0xDDDDDDDD。

#include <iostream>
#include <string.h>
#include <vector>

using std::cout;
using std::endl;

template <class Data>

class Node
{
public:
    Node* next;
    Data data;
};

template <class Data>

class List
{

private:
    Node<Data>* head;
    Node<Data>* tail;
    int count;

public:
    //constructor
    List()
    {
        count = 0;
        head = nullptr;
        tail = nullptr;
    }


    int size()
    {
        return count;
    }


    void msg_empty_list()
    {
        cout << "The list is not modified since it is empty." << endl;
    }


    int push_back(Data data)
    {
        Node<Data>* node = new Node<Data>;
        node->data = data;
        node->next = nullptr;

        if (head == nullptr)
        {
            head = node;
            tail = node;
        }
        else if (head != nullptr)
        {
            tail->next = node;
            tail = tail->next;
        }

        count++;
        return count;
    }


    int push_front(Data data)
    {
        Node<Data>* node = new Node<Data>;
        node->data = data;
        node->next = nullptr;

        if (head == nullptr)
            head = node;
        else if (head != nullptr)
        {
            node->next = head;
            head = node;
        }

        count++;
        return count;
    }


    int pop_front(void)
    {
        if (head == nullptr)
            return -1;
        else if (head != nullptr)
        {
            Node<Data>* temp;
            temp = head;
            head = head->next;
            delete temp;

            count--;
            return count;
        }
    }


    int pop_back(void)
    {
        if (head == nullptr)
            return -1;
        else if (head != nullptr)
        {
            Node<Data>* temp = head;
            while (temp->next != tail)
                temp = temp->next;

            delete tail;
            tail = temp;

            count--;
            return count;
        }
    }


    int remove_at(int index)
    {
        if (head == nullptr)
            return -1;
        else if (head != nullptr)
        {
            cout << "Specified index = " << index << endl;
            if (index == 0)
            {
                pop_front();
            }
            else if (index == -1)
            {
                pop_back();
            }
            Node<Data>* temp = head;
            Node<Data>* rmv;
            int countIndex = 0;

            while (countIndex < index - 1)
            {
                temp = temp->next;
                countIndex++;
            }

            rmv = temp->next;
            temp->next = temp->next->next;
            delete rmv;

            count--;
            return count;
        }
    }


    void reverse()
    {
        Node<Data>* temp = nullptr;
        Node<Data>* prev = nullptr;
        Node<Data>* current = head;

        while (current != nullptr)
        {
            temp = current->next; // where I get error "Unhandled exception thrown: read access violation. **current** was 0xDDDDDDDD."
            current->next = prev;
            prev = current;
            current = temp;
        }
        head = prev;
    }


    void print()
    {
        Node<Data>* temp = head;

        if (head == nullptr)
            return;

        for (int i = 0; i < count - 1; i++)
        {
            cout << temp->data << ", ";
            temp = temp->next;
        }

        cout << temp->data;
    }


    ~List()
    {
        Node<Data>* temp = head;

        while (temp->next != nullptr)
        {
            temp = temp->next;
            delete head;
            head = temp;
        }

    }
};


int main()
{
    Node<int> x;
    Node<bool> y;
    Node<char> n;
    List<int> list;

    //insert items into list
    for (int i = 0; i < 10; i++)
    {
        list.push_back(i);
    }

    cout << "Original list[size=" << list.size() << "]: ";
    //print the list
    list.print();
    cout << endl;

    // push a node to the beginning of the list
    cout << endl << "==> Push a node to the head" << endl;
    list.push_front(-1);
    cout << "Modified list[size=" << list.size() << "]: ";
    list.print();
    cout << endl;


    // pop the head of the list
    cout << endl << "==> Pop a node from the head" << endl;
    if (list.size() == 0)
        list.msg_empty_list();
    else
    {
        list.pop_front();
        cout << "Modified list[size=" << list.size() << "]: ";
        list.print();
        cout << endl;
    }

    /*
    // pop the tail of the list
    cout << endl << "==> Pop a node from the tail" << endl;
    if (list.size() == 0)
        list.msg_empty_list();
    else
    {
        list.pop_back();
        cout << "Modified list[size=" << list.size() << "]: ";
        list.print();
        cout << endl;
    }
    */

    // delete the node at the specified index
    cout << endl << "==> Delete the node at the specified index" << endl;
    if (list.size() == 0)
        list.msg_empty_list();
    else
    {
        list.remove_at(5);
        cout << "Modified list[size=" << list.size() << "]: ";
        list.print();
        cout << endl;
    }


    // reverse the list
    cout << endl << "==> Reverse the list" << endl;
    if (list.size() == 0)
        list.msg_empty_list();
    else
    {
        list.reverse();
        cout << "Modified list[size=" << list.size() << "]: ";
        list.print();
        cout << endl;
    }

    return 0;
}

我可以发现您的代码中的一些错误,但让我们专注于 pop_back() 函数:

    int pop_back(void)
    {
        if (head == nullptr)
            return -1;
        else if (head != nullptr) // 1)
        {
            Node<Data>* temp = head;
            while (temp->next != tail) // 2)
                temp = temp->next;

            delete tail;
            tail = temp; // 3)

            count--;
            return count;
        }
    }
  1. 请不要这样做:if (a == nullptr) {...} else if (a != nullptr) {...} 是多余的。把第二个 if 放在一边。它让 reader 相信可能存在第三种情况。
  2. 幸运的是这通常有效,但其他一些方法没有正确更新尾指针,所以这可能永远不会是真的。当列表中只有一个元素时验证 pop_front 方法。其他功能可能也有类似的问题。
  3. 这是您观察到的实际问题。您没有将新尾部元素的 next 指针设置为空,而是指向现在已删除的尾部。在此行之后插入 tail->next = nullptr