【问题标题】:Does the "delete" statement doubly free an object?“删除”语句是否双重释放对象?
【发布时间】:2010-08-11 01:29:49
【问题描述】:

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

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

【问题讨论】:

    标签: vector stl erase


    【解决方案1】:

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

    【讨论】:

    • 谢谢你的回答!!我有这个问题,因为在另一个程序中我使用 map 并且在我调用 erase() 以从地图中删除对象 * 后取消引用对象 * 时程序崩溃。 (我正在使用 VC++ 6)所以我想知道 vector.erase() 是否也释放了对象。
    【解决方案2】:

    看起来不是;如果您有一个指向对象的指针向量,则调用 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());
    

    【讨论】:

    • 感谢您的回答!但不是你的最后一个语句 object_list.erase(std::remove(object_list.begin(), object_list.end(), NULL), object_list.end());清除所有对象,无论死活?
    • 否 - remove 从列表中删除所有等于 NULL 的元素,并在最后一个有效元素之后返回一个迭代器。然后,erase 调用将向量截断为这个新长度。
    猜你喜欢
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 2021-12-10
    相关资源
    最近更新 更多