Инициализировать указатели C ++ в ZERO после удаления? - PullRequest
2 голосов
/ 24 марта 2011

В C ++ мы используем оператор delete для удаления объектов большую часть времени.

delete не делает значение указателя NULL. Есть ли способ, которым это может быть достигнуто автоматически?

, например

int *p = new int;
delete p;  // this should deallocate object pointed by p
           // and also initialized value of p = NULL

Ответы [ 10 ]

14 голосов
/ 24 марта 2011

Есть две проблемы с вашим предложением.

Ложное чувство безопасности

Ваше предложение вызывает ложное чувство безопасности.Конечно, стандарт гарантирует, что если вы вызовете delete по нулевому указателю, он не взорвется.Однако вы забыли один крошечный факт: на ваш объект нет ни одного указателя.

int* p = new int(8);
int* q = p;
delete p; p = 0;
delete q; // Undefined Behavior

Поэтому такая практика бесполезна.И поскольку ложное чувство безопасности хуже, чем отсутствие безопасности вообще , я на самом деле категорически против этого.В надежде, что люди подумают, прежде чем применять delete nilly-willy.

, что подводит нас ко второму вопросу

Не смей ли ты когда-либо использовать delete* 1020?*

delete должен быть зарезервирован для разработчиков интеллектуальных указателей или других контейнеров .Применяется следующее:

  • Только для экспертов
  • (Эксперты) Не *

* Возможно, уже существует отлаженная реализация длячто вы пытаетесь достичь.

Существует куч существующих инструментов для управления памятью:

  • вездесущие различные разновидности интеллектуальных указателей:std::unique_ptr или std::auto_ptr (в зависимости от вашей версии C ++), std::scoped_ptr, std::shared_ptr (и его сравнение std::weak_ptr, или их эквивалент boost / tr1)
  • вездесущие различные варианты контейнеров: boost::array, boost::scoped_array, std::vector (и со)
  • и менее известные, но полезные в ОО: boost::ptr_vector (и со)
  • есть даже boost::intrusive_ptr и библиотеку Boost Intrusive Containers или библиотеку Boost MultiIndex (с производной BiMap)
  • и, возможно, несколько других библиотек Boost, возможно, более специализированных, таких как Boost.Signals

С такиминеоднородная дикая природа, трудно подумать, что вы вдруг обнаружили новый способ использованияНг данные, которые настолько отличаются от того, что мы делаем, что вам нужно что-то еще.И если у вас есть, не стесняйтесь опубликовать его, мы поможем вам понять, как использовать эти инструменты в соответствии с вашей ситуацией (или дадим вам подсказки о том, как создать новую форму интеллектуального указателя).

5 голосов
/ 24 марта 2011

В любом случае это не очень помогает, потому что может быть несколько указателей на удаленный объект.

int* p = new int;

int* q = p;

delete p;   // how do we NULL q?

Лучше всего использовать delete перед тем, как p выйдет из области видимости. Или используйте стандартные контейнеры, чтобы нам вообще не нужно было создавать новые / удалять.

4 голосов
/ 24 марта 2011

без каких-либо испытаний, я даю вам это:

template <typename T> void deleteAndNull(const T*& pointer){
    delete pointer;
    pointer = 0;
}
4 голосов
/ 24 марта 2011

Вы можете написать свою собственную функцию-оболочку или макрос, который бы это делал.Однако в общем случае это сложно, потому что вы можете передавать значения в оператор удаления.И что тогда ему следует присвоить NULL?

1 голос
/ 24 марта 2011

Может быть использование auto_ptr с указателями сэкономит ваше время.

0 голосов
/ 24 марта 2011

Это невероятно плохая практика.

Они сказали, что это спасет вашу программу от сбоя при двойном удалении.Увы, делая указатель NULL после того, как вы удалили объект, на который он указывал, просто замаскируйте проблему: ваша программа содержит ошибку.

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

0 голосов
/ 24 марта 2011

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

0 голосов
/ 24 марта 2011

Это просто написать так:

template<class T>
void safe_delete(T*& p)
{
    delete p;
    p = NULL;
}
int main()
{
    int* p = new int;
    safe_delete(p);

    double* p1 = new double;
    safe_delete(p1);

}

Будьте осторожны, не используйте это с массивами:)

0 голосов
/ 24 марта 2011

Самый простой способ сделать это - переопределить оператор удаления на

  • очистить память
  • Обнулить указатель

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

0 голосов
/ 24 марта 2011

Вы можете написать свою собственную функцию, чтобы сделать это:

void deleteAndReset (void** p)
{
    delete *p;
    *p = null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...