C ++ SLList - Удалить временный узел из кучи? - PullRequest
0 голосов
/ 08 ноября 2018

Я изучаю связанные списки, и я думал, что правило состоит в том, что каждый new должен отвечать delete, чтобы очистить динамически распределенную память. Вот мой код, в котором я создаю 3 узла в списке, каждый раз создавая узел temp с Node *temp = new Node; в функции createNode. У меня такой вопрос, разве это не динамически распределяется в куче, и мне нужно delete temp;? Без этого мой код работает нормально, но когда я добавляю delete temp; в конце функции, я получаю ошибку нарушения доступа для чтения. Разве это не должно иметь значения, так как temp больше не используется после завершения функции? Надеюсь, что это имеет смысл, спасибо за вашу помощь.

#include <iostream>
#define Log(x) std::cout << x << std::endl;

struct Node
{
    int data;
    Node *next;
};

class SLList
{
private:
    Node *head;
    Node *tail;

public:
    SLList() 
    {
        head = NULL;
        tail = NULL;
    }

    void createNode(int value)
    {
        Node *temp = new Node;
        temp->data = value;
        temp->next = NULL;

        if (head == NULL)
        {
            head = temp;
            tail = temp;
        } 
        else
        {
            tail->next = temp;
            tail = temp;
        }
    }

    void printList()
    {
        Node *temp;
        temp = head;
        while (temp != NULL)
        {
            Log(temp->data);
            temp = temp->next;
        }
    }
};

int main()
{
    SLList list1;
    list1.createNode(5);
    list1.createNode(7);
    list1.createNode(2);

    list1.printList();

    std::cin.get();
}

Ответы [ 2 ]

0 голосов
/ 08 ноября 2018

A delete для каждого new является правильным, но не сообщает , когда целесообразно удалить. Вы не можете удалить, пока у вас есть указатель (и) на данные, и вы намерены использовать эти значения указателя позже, чтобы разыменовать их.

Указатели на узлы находятся внутри списка и в указателе заголовка, поэтому вы пока не можете удалить эти узлы. Вы можете сделать это только тогда, когда любые указатели, которые были на любом данном узле, будут очищены или иным образом оставлены без разыменования до назначения им нового значения.

0 голосов
/ 08 ноября 2018

Это правда, что вы должны освободить динамически распределенную память, но вы пытаетесь сделать это в неправильное время.

Когда вы вызываете Node *temp = new Node;, вы не создаете временный узел, вы создаете узел в куче и делаете временный указатель на него в стеке. После того, как вы добавили этот узел в список, вам больше не нужен этот указатель (его значение хранится в вашем объекте SList), но вам все еще нужен объект, на который он указывает.

Итак:

  • Да, вы должны освободить память, вызвав delete
  • Нет, вы не должны делать это внутри createNode метода, потому что вам все еще нужны эти данные. Освободите память, когда она вам не нужна: когда вы удалите элемент из списка.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...