如何擦除和删除存储在向量中的对象的指针?

Ton*_*y R 30 c++ iterator vector erase visual-c++

我有一个向量存储指向动态实例化的许多对象的指针,我正在尝试迭代向量并删除某些元素(从向量中移除并销毁对象),但我遇到了麻烦.这是它的样子:

    vector<Entity*> Entities;
    /* Fill vector here */
    vector<Entity*>::iterator it;
    for(it=Entities.begin(); it!=Entities.end(); it++)
        if((*it)->getXPos() > 1.5f)
            Entities.erase(it);
Run Code Online (Sandbox Code Playgroud)

当任何实体对象到达xPos> 1.5时,程序崩溃并出现断言错误......任何人都知道我做错了什么?

我正在使用VC++ 2008.

小智 41

您需要小心,因为erase()将使现有迭代器无效.但是,ir返回一个可以使用的新的有效迭代器:

for ( it = Entities.begin(); it != Entities.end(); ) {
   if( (*it)->getXPos() > 1.5f ) {
      delete * it;  
      it = Entities.erase(it);
   }
   else {
      ++it;
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 指针没有析构函数.只有当它是实体值的集合时,才会调用向量中的事物的析构函数.因此,如果您希望避免内存泄漏,则必须调用delete. (4认同)

rlb*_*ond 9

执行此操作的"正确"方法是使用算法:

#include <algorithm>
#include <functional>

// this is a function object to delete a pointer matching our criteria.
struct entity_deleter
{
    void operator()(Entity*& e) // important to take pointer by reference!
    { 
        if (e->GetXPos() > 1.5f)
        {
            delete e;
            e = NULL;
        }
}

// now, apply entity_deleter to each element, remove the elements that were deleted,
// and erase them from the vector
for_each(Entities.begin(), Entities.end(), entity_deleter());
vector<Entity*>::iterator new_end = remove(Entities.begin(), Entities.end(), static_cast<Entity*>(NULL));
Entities.erase(new_end, Entities.end());
Run Code Online (Sandbox Code Playgroud)

现在我知道你在想什么.你认为其他一些答案更短.但是,(1)这种方法通常编译为更快的代码 - 尝试比较它,(2)这是"正确的"STL方式,(3)傻错误的机会较少,(4)它更容易阅读一旦你可以阅读STL代码.这是非常值得学习STL编程的,我建议你查看Scott Meyer的伟大着作"Effective STL",它有很多关于这类东西的STL技巧.

另一个重要的一点是,通过在操作结束之前不擦除元素,元素不​​需要被拖曳.GMan建议使用列表来避免这种情况,但使用这种方法,整个操作都是O(n).相反,上面的Neil代码是O(n ^ 2),因为搜索是O(n)并且删除是O(n).

  • 恕我直言,显然不如显式循环清晰. (4认同)