Ошибка подтверждения: вызов деконструктора узла списка - PullRequest
0 голосов
/ 19 февраля 2011

Я студент информатики с задачей создания динамической структуры данных, связанных списков.В настоящее время я работаю над односвязным списком и успешно создал функциональность для добавления, удаления и вывода всех данных об узлах.

Однако, помня, что мой лектор по «расширенному программированию» заявил, что во избежание путаницы и другихпроблемы, при удалении узлов из списка или освобождении памяти любого объекта, это должно произойти внутри деконструктора.Поэтому я переместил:

delete[] _del;

, который работал нормально и переместил его в деконструктор узлов:

#include "Node.h"

// Node.cpp

Node::Node(const int &inData, const int &inId)
{
    _id = inId;
    _data = inData;
    nextNode = NULL;
}

// Deconstructor to delete the node when using List.Del()
Node::~Node()
{
    delete[] this;
}

В моем списке деконструктор узла вызывается через указатель, например:

_del->~Node();

Что дает мне ошибку утверждения.Я предполагаю, что это мое использование «this» в деконструкторе узла?

Спасибо за ваше время.

Ответы [ 4 ]

2 голосов
/ 19 февраля 2011

Прежде всего, вы не должны вызывать деструктор объектов напрямую, если только вы не пишете распределитель и не используете новое размещение при его создании.Во-вторых, вы должны delete, а не delete[], если вы также не использовали new[].И, наконец, delete this - вредная привычка, но легальная в соответствии со стандартом.Почему бы вам просто не позвонить delete theNode вместо всего этого?

РЕДАКТИРОВАТЬ: адресовать некоторые комментарии / дополнительные вопросы.

Чтобы выделить один экземпляр в куче, вы используете theNode = new Node,Возвращенный указатель должен быть освобожден с помощью delete theNode.Вызов new выделит память, а затем вызовет Node::Node(), конструктор, чтобы он мог установить свое внутреннее состояние.Вызов delete удалит Node::~Node(), а затем освободит выделенную память.Деструктор отвечает за очистку всего, что использует Node, но не памяти, используемой самим Node.

Чтобы выделить массив узлов, вы используете theNodes = new Node[10];.Вы удаляете их с помощью delete[] theNodes.Смешивать new / delete с new [] / delete [] - неопределенное поведение.

Размещение new - это метод, в котором вы хотите создать объект в уже выделенной памяти .В этом случае у вас есть единственная веская причина для непосредственного вызова деструктора: вы хотите деконструировать объект (он же позволяет ему очиститься) без , а также освобождает выделенную для него память.

Вызов delete this допустим, например, для функции Suicide(), если вы не ссылаетесь на «this» или любых членов удаленного экземпляра после вызова delete this.Это правильная методика, например, для объектов с подсчетом ссылок, но часто считается чем-то, чего вам следует избегать, если вам это действительно не нужно.

Правильное решение для вас довольно простое, когда вы сейчас вызываете ~Node, простоdelete theNode вместо.

1 голос
/ 19 февраля 2011

Как правильно удалить объект из своего деконструктора?

Это не так. Деструктор очищает ресурсы , принадлежащие объекту, а не самому объекту.

Вы должны отказаться от использования delete, и все, что выделило Node (ваш список?), Должно быть лучше, чтобы освободить его. Самый простой способ сделать это - иметь ровно одну точку в вашем классе списка, которая выделяет и добавляет узлы в список, и ровно одну точку, которая удаляет и освобождает узлы (упомянутый метод Del). Деструктор вашего класса списка должен вызывать Del несколько раз, пока список не станет пустым.

1 голос
/ 19 февраля 2011
Node::~Node()
{
    delete[] this;
}

Неопределенное поведение. Скорее всего, вылетит ваша программа!

Кстати, есть разница между delete this и delete[] this. Хотя delete this может быть хорошо, иногда , но delete[] this нет, поскольку this никогда не может быть выделено с помощью new[]. Это не указатель на массив. Это указатель на ОДИН объект!

0 голосов
/ 19 февраля 2011

Как и предыдущий ответ предполагает, что ваш деконструктор имеет неопределенное поведение.По следующей причине:

Когда выполняется

delete[] _del;

.он пытается удалить тот же объект, который вы пытаетесь удалить в его деконструкторе

delete[] this;

Что означает текст вашего курса, так это: если вы хотите очистить любую память, связанную с удаляемым объектом, котораявыпущен в деконструкторе этого объекта, а также.Например, если id и / или данные были указателями:

Node::~Node()
{
   delete _id;
   delete _data;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...