指针元素删除传染媒介

时间:2014-04-14 15:26:31

标签: c++ vector delete-operator

我有一个指针向量,我想删除一个条目。删除条目后,我检查向量的大小,并没有减少。我应该多做一件事吗?

printf("size of vector before %d \n", m_obj.size());
for(std::vector<object*>::iterator it = m_obj.begin(); it != m_obj.end(); ++it)
{
  if((*it)->m_id == p_id)
  {
     delete *it;
  }
}

printf("size of vector after %d \n", m_obj.size());

5 个答案:

答案 0 :(得分:2)

您对delete *it的调用仅删除向量中该条目指向的对象。您不会修改矢量本身。

要从矢量中删除元素,请使用erase方法:

 delete *it;
 it = m_obj.erase(it);

请注意,擦除会使当前迭代器无效,因此您可能希望将erase调用的返回值分配给it变量。在删除循环中的多个条目时,请注意不要意外跳过元素。返回的迭代器将指向之后的元素已被删除的元素将再次> for循环

解决此问题的最简单方法是使用STL algorithm来删除元素。如果条目也拥有其所有者的所有权,则此方法效果最佳,因此您可能需要考虑使用smart pointers的向量(如建议的in the comments),因此您不必担心显式调用{ {1}}。

答案 1 :(得分:2)

           +----------+         +-------------+
           | object * |-------->| heap memory |
           +----------+         +-------------+
it-------->| object * |-------->| heap memory |
           +----------+         +-------------+
           | object * |-------->| heap memory |
           +----------+         +-------------+
           | object * |-------->| heap memory |
           +----------+         +-------------+

delete *it之后:

           +----------+         +-------------+
           | object * |-------->| heap memory |
           +----------+         +-------------+
it-------->| object * |-------->
           +----------+         +-------------+
           | object * |-------->| heap memory |
           +----------+         +-------------+
           | object * |-------->| heap memory |
           +----------+         +-------------+

您还需要以某种方式擦除向量中的指针元素。请记住,在迭代期间您无法erase(it),因为它会使您的迭代器失效。

答案 2 :(得分:0)

您只释放指针下分配的内存。你没有删除指针本身。

调用delete后,将指针值设置为NULL。在for循环之后使用std::remove_if对元素进行NULL检查。

答案 3 :(得分:0)

删除对象不会从向量中删除指向它的指针,它只会释放指针指向的内存。在释放元素后,您需要在向量上显式调用erase

答案 4 :(得分:0)

拥有拥有 原始指针的STL容器(例如std::vector)通常是一个坏主意。这可能是泄漏的来源:例如如果在某处抛出异常,则会调用向量析构函数,但这将删除原始拥有指针!所以他们的相关资源被泄露了 此外,您必须提供明确的清理代码等。

您可能希望使用std::vector<Object>或{{1>} 智能指针,例如std::vectorvector<shared_ptr<Object>>(后者在C ++ 11中可用,这要归功于移动语义,如果vector<unique_ptr<Object>>是对象的唯一所有者,那么这是一个很好的解决方案,并且没有共享所有权。)

您可能还想使用 vector 算法。特别是,要从remove_if()中删除满足某些精确条件的项目,您可能需要使用所谓的 erase-remove idiom

vector

使代码更清晰(特别是如果一个人不知道/识别擦除 - 删除习语),就可以编写一个小帮助函数来实现这个习语:

// Use a vector of *smart pointers* (shared_ptr or unique_ptr).
typedef std::shared_ptr<Object> ObjectPtr;
std::vector<ObjectPtr> v;

...
...

// Use the erase-remove idiom to erase items satisfying a particular condition.
v.erase( std::remove_if(v.begin(), v.end(), [&](const ObjectPtr & p) { 
    return p->m_id == deleteId; // Erasing condition 
}), v.end());

然后像这样称呼它:

// Helper function to implement the erase-remove idiom for std::vector.
template <typename T, typename Predicate>
void erase_if(std::vector<T>& v, Predicate p) {
    v.erase(std::remove_if(v.begin(), v.end(), p), v.end());
}

请注意,由于使用了// Simplified code: just pass the vector 'v' and the erasing condition // (in this case using a simple lambda). // Uses the erase-remove idiom under the hood. // erase_if(v, [&](const ObjectPtr & p) { return p->m_id == deleteId; }); 算法和删除删除习惯用法,您的代码的语义级别会被提升:您不能t读取显式remove_if循环和迭代器递增;你可以只读取代码的清晰意图,即删除满足给定条件的项目。


PS :您可能还想阅读:"How do I erase elements from STL containers?"