如果使用remove_if和items是指向对象的指针,如何删除向量中的项?

时间:2011-11-01 14:31:27

标签: c++ memory-leaks vector erase remove-if

我担心通过执行以下操作会遇到内存泄漏问题:

(示例代码)

class myItem //random container stuff mostly. All primatives.
{
    int index;
    char* name;
    int val1;
    int val2;
};

class vecList
{

    vector< myitem* > *myVec;

    void delete()
    { 
        MyVec->erase(std::remove_if(myVec->begin(), MyVec->end(), IsMarkedToDelete), MyVec->end()); //leak here?
    }
};

如果它是指针,擦除不会释放内存,对吗?如果我没有使用remove_if,我可以在销毁之前调用指针上的delete。在这种情况下我该怎么做?智能指针?我不想用它们重新实现所有内容,我真的不想添加boost库。

谢谢!

4 个答案:

答案 0 :(得分:8)

您可以在IsMarkedToDelete函数返回true时删除该项。

答案 1 :(得分:3)

如果对象的唯一指针在向量中,那么你就是 一旦拨打remove_if,就会泄露内存。 remove_if移动了 你要记下的指针,但它没有说什么 它返回的迭代器后面的值。因此,如果你有东西 例如[a, b, c, d](其中ab等表示不同的指针), 然后在e = remove_if( v.begin(), v.end(), matches(b) )之后,你的 矢量可能(也可能会)看起来像[a, c, d, d]e 指向第二个db的所有痕迹都永远丢失。

显而易见的解决方案是在shared_ptr中使用vector;这个 将确保最终从vector删除的任何指针 将被删除。如果做不到这一点,你可以使用两次传球:第一次传球 是一个for_each,类似于:

struct DeleteIfCondition
{
    void operator()( ObjectType* &ptr ) const
    {
        if ( condition( *ptr ) ) {
            ObjectType* tmp = ptr;
            ptr = NULL;
            delete tmp;
        }
    }
};

std::for_each( v.begin(), v.end(), DeleteIfCondition() );

作为功能对象,后跟:

v.erase( std::remove( v.begin(), v.end(), NULL ), v.end() );

答案 2 :(得分:1)

您可以使用remove_if,然后从返回值使用for_each直到结束,然后删除。当然,这会使你的代码更长一些。另一种可能性是存储shared_ptr指针,如果您的代码与此一致。

正如本杰明指出的那样,上面是一个直言不讳的谎言,所以你只剩下“另一种可能性”。

答案 3 :(得分:0)

您可以使用此功能:

template<typename T, typename TESTFN>
void delete_if(std::vector<T*>& vec, TESTFN&& predicate)
{
   auto it = remove_if(vec.begin(), vec.end(), [&](T* item) {
      if (predicate(item)) {
         delete item;
         return true;
      }
      return false;
   });
   vec.erase(it, vec.end());
}

例如:

delete_if(MyVec, [](T* item) { return item->index == 5; });