Оператор «delete» дважды освобождает объект? - PullRequest
2 голосов
/ 11 августа 2010

Является ли оператор "delete" ниже "вдвойне свободным" объектом?

(...object_list is a global vector<object*>...)

vector< object * >::iterator     it, eit, iter;
object *p_object;
vector< object * >   dead_objects;

it  = object_list_.begin();
eit = object_list_.end();

//---collect pointers of all dead objects to dead_objects vector
for ( ; it != eit; it++ )
{
    p_object = *it;
    if ( p_object->is_dead() == false )
        continue;

    dead_objects.push_back( p_object );
}

//---free every dead object from the global object_list
for ( iter = dead_objects.begin(); iter != dead_objects.end(); iter++ )
{
    p_object = *iter;

    it  = object_list_.begin();
    eit = object_list_.end();

    for ( ; it != eit; it++ )
    {
        if ( *it != p_object )
            continue;

        object_list_.erase( it );
        delete p_object;
        break;
    }
}

Я задаю вопрос, потому что вышеприведенное выражение erase() должно было вызвать деструктор объекта и уже освободить его, не так ли?

Ответы [ 2 ]

2 голосов
/ 11 августа 2010

erase() вызывает деструктор для объекта, но деструктор типа указателя (такого как object * здесь) ничего не делает - он НЕ вызывает delete для указателя.Если вы хотите, чтобы он вызывал delete, вам нужно использовать некоторый объект (например, auto_ptr<object *>), который вызывает delete.

0 голосов
/ 11 августа 2010

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

Всего пара предложений - IMO ваш код будет более понятным, если вы используете алгоритмы STL, такие как std::findвместо того, чтобы перебирать все ваши векторы вручную.Я не уверен, в чем смысл dead_objects vs object_list - вы, кажется, ничего не получите, сохранив их во временном векторе, но что-то могло быть потеряно при копировании кода в SO.И std::vector не является оптимальным для множества случайных стираний, подобных этому, поскольку erase выполняется за линейное время - std::remove с последующим erase будет более эффективным подходом.Например:

for(vector<object*>::iterator it = object_list.begin(); it != object_list.end(); ++it) {
    if((*it)->is_dead()) {
        delete *it;
        *it = NULL;
    }
}
object_list.erase(std::remove(object_list.begin(), object_list.end(), NULL), object_list.end());
...