2

下面的“删除”语句是否“双重释放”对象?

(...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()上面的语句应该调用对象的析构函数并已经释放它,不是吗?

4

2 回答 2

2

erase()确实调用了对象的析构函数,但是指针类型的析构函数(例如object *这里)什么都不做——它不会在指针上调用 delete。如果你想让它调用delete,你需要使用一些调用delete的对象(例如auto_ptr<object *>)。

于 2010-08-11T01:48:36.177 回答
0

看起来不是;如果你有一个指向对象的指针向量,调用 erase() 删除其中一个只是从向量中删除指针。您仍然需要自己删除它 - 这是因为 STL 容器主要设计用于按值收集对象。

std::find只是一些建议-如果您使用 STL 算法而不是手动遍历所有向量,IMO 您的代码会更清晰。我不确定 dead_objects 与 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());
于 2010-08-11T01:47:45.740 回答