2010-11-21 1 views
6

Почему нужно было бы явно очистить переменную-член вектора (включен в dtor (см. Код ниже). Каковы преимущества очистки вектора, хотя он будет уничтожен сразу после последней строки dtor код будут выполненыНужно ли мне аннулировать переменную-член в деструкторе?

class A 
{ 
~A() 
{ 
    values.clear(); 
} 

private: 
    std::vector <double> values_; 
}; 

аналогичный вопрос о следующем коде:

class B 
{ 
~B() 
{ 
    if (NULL != p) 
    { 
     delete p_; 
     p_ = NULL; 
    } 
} 

private: 
    A * p_; 
}; 

Поскольку не существует никакого способа dtor будет вызван дважды, поэтому свести к нулю p_ затем

+0

Привет, Майкл, вы должны попробовать очистить свой титул. Тогда вы получите больше ответов. –

+1

Micheal FTFY. Если вы чувствуете, что мое редактирование было плохим, не стесняйтесь возвращаться. –

ответ

11

в? класс A, нет абсолютно никаких причин для .clear()vector-тип переменной-элемента в деструкторе. Деструктор vector будет .clear()vector, когда он называется.

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

delete p_; 

Там нет необходимости, чтобы проверить, является ли p_ != NULL первым, потому что delete NULL; определяется не быть не оп. Также нет необходимости устанавливать p_ = NULL после того, как у вас есть delete d, потому что p_ не может быть законно доступным после того, как объект, из которого он является членом, будет уничтожен.

Тем не менее, вам редко приходится использовать delete в коде C++. Вы должны предпочесть использовать управление ресурсами с ограничением видимости (SBRM, также называемое инициализацией приобретения ресурсов) для автоматического управления сроками ресурса ресурсов.

В этом случае вы можете использовать интеллектуальный указатель. boost::scoped_ptr и std::unique_ptr (от C++ 0x) являются хорошим выбором. Ни один из них не должен иметь накладных расходов по сравнению с использованием необработанного указателя. Кроме того, они обе подавляют генерацию неявно объявленного конструктора копирования и оператора присваивания копий, который обычно вы хотите, когда у вас есть переменная-член, которая является указателем на динамически выделенный объект.

+4

Хороший ответ, за исключением кода «редко использовать delete в C++». Я согласен с тем, что такие вещи, как auto_ptr и unique_ptr, заботятся о многих ситуациях, абсолютно неверно утверждать, что «удаление» должно быть/редко/использовано. –

+5

@edA: Нет, не совсем. Его редко следует использовать. Дайте нам ситуацию, когда вы думаете, что вам это нужно, мы сделаем ее более чистой и безопасной. ** Все ** ресурсы должны быть обернуты, поэтому вам нужно только использовать обертку. Если у вас есть «удаление» в любом месте, кроме деструктора, вы сделали это неправильно – GManNickG

+5

@edA: Я поддерживаю это утверждение. Я не написал одно выражение 'delete' в новом производственном коде за последние два года (до этого я был полным noob, когда дело доходило до написания правильного кода на C++). –

0

В случае p_ нет необходимости устанавливать его равным нулю в деструкторе, но он может быть полезным защитным механизмом. Представьте себе случай, когда у вас есть ошибка, и что-то по-прежнему содержит указатель на объект B после его удаления:

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

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

+0

Это не должно быть проблемой. Если несколько вещей ссылаются на что-то, что-то должно было быть помещено в 'shared_ptr'. Задача решена. – GManNickG

+2

Если у вас действительно есть ошибка, установка указателя на нуль скроет ошибку. Это действительно то, что вы хотите? Нет, вы хотите, чтобы он как можно скорее потерпел крушение. – fredoverflow

+0

@Fred, да, но оставить его в комплекте не вызовет. Вы пытались отследить ошибку двойного удаления? Они не забавны. –

2

В вашем втором примере нет причин устанавливать p_ на нуль, особенно потому, что это делается в деструкторе, что означает, что время жизни p_ закончится сразу же после этого.

Кроме того, нет смысла сравнивать p_ с номером до звонка delete, так как выражение delete выполняет эту проверку внутренне. В вашем конкретном искусственном примере деструктор должен просто содержать delete p_ и отметить еще. Нет if, без установки p_ null.

Смежные вопросы