Удаление объектов в с ++ - PullRequest
       63

Удаление объектов в с ++

0 голосов
/ 18 сентября 2011

У меня есть LinkedList с узлом, который имеет поле:

void* _data;

Теперь я хочу удалить эти данные, но не могу знать, будут ли данные примитивами или объектами, которые были динамически распределены.

итак, если написать:

~Node() {
  delete _node;
}

и данные - это объект, который был динамически распределен, вызовет ли он деструктор объекта или у меня будет утечка памяти?

Так, как я могу заставить это работать?

Ответы [ 4 ]

7 голосов
/ 18 сентября 2011

Не делайте этого!

Вызов delete на void pointer является неопределенным поведением . [Ссылка ниже]
Неопределенное поведение означает, что что-то может случиться, программа может иногда зависать или иногда работать, но вы не можете предсказать ее поведение в любое время, что является очень плохим способом программирования.

Как вы правильно поняли с помощью void*, оператор delete никак не может определить, какой деструктор класса ему нужно вызвать, в конце концов, что приведет к неопределенному поведению.

Так, как я могу заставить эту работу работать?
Как я понимаю, Ваше намерение иметь указатель void* состоит в том, чтобы иметь реализацию общего списка ссылок.C ++ уже предоставляет шаблонный общий список ссылок std :: list для этой цели. Вы можете использовать его, поскольку нет смысла заново изобретать колесо, и, скорее всего,стандартная реализация списка ссылок будет лучше, чем любая настраиваемая версия общего списка ссылок.

Если вы все еще хотите иметь свою собственную версию списка ссылок.Вы должны реализовать универсальный класс списка ссылок на шаблоны, что делает std :: list .

Посмотрите на Программирование шаблонов .


Ссылка:
Согласно C ++ 03 Стандартный раздел 5.3.5 / 3:

В первом варианте (удаление объекта), если статический тип операнда отличается от его динамического типа, статический типдолжен быть базовым классом динамического типа операнда, а статический тип должен иметь виртуальный деструктор или поведение не определено.Во втором варианте (удаление массива), если динамический тип удаляемого объекта отличается от его статического типа, поведение не определено (FootNote 73).

Foot Note 73)

Это означает, что объект нельзя удалить, используя указатель типа void *, поскольку нет объектов типа void

3 голосов
/ 18 сентября 2011

Если вам нужно это поведение, используйте шаблон .Ваш код, как написано, не может знать, какой деструктор вызывать.

2 голосов
/ 18 сентября 2011

Когда _node имеет тип void*, delete _node всегда неверен, потому что тип операнда, используемого с delete, всегда должен быть указателем на динамический тип создаваемого объекта или на тип, который являетсябазовый класс этого типа, при условии, что тип базового класса имеет виртуальный деструктор.Ясно, что void* не может выполнить ни одну из частей этого требования.

Если вы используете void*, вам нужно найти способ возврата к исходному типу перед вызовом delete.Альтернативный подход будет состоять в том, чтобы использовать что-то вроде std::shared_ptr<void>, которое можно использовать таким образом, чтобы соответствующий удалитель сохранялся во время создания (или сброса) и автоматически вызывался с уничтоженным узлом.

0 голосов
/ 18 сентября 2011

Удаление пустого указателя опасно. Компиляторы могут предупреждать или отклонять ваш код. Стандарт C ++ говорит, что вы не должны этого делать.

На практике, если компилятор принимает ваш код, он освобождает только память без вызова деструктора.

...