繁体   English   中英

指针元素删除传染媒介

[英]Vector of pointers element deletion

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

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());

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

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

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

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

解决此问题的最简单方法是使用STL算法来删除元素。 如果条目也拥有其所有者的所有权,那么这种方法效果最好,因此您可能需要考虑使用智能指针向量(如注释中所示 ),因此您根本不必担心显式调用delete

           +----------+         +-------------+
           | 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) ,因为它会使迭代器失效。

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

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

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

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

您可能想要使用std::vector<Object>智能指针std::vector ,例如vector<shared_ptr<Object>>vector<unique_ptr<Object>> (后者可用,因为C ++ 11谢谢移动语义,如果vector是对象的唯一所有者,并且没有共享所有权,那么这是一个很好的解决方案。

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

// 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; });

请注意,由于使用了remove_if 算法和erase-remove习惯用法,因此提高了代码的语义级别 :您不会读取显式for循环和迭代器递增; 你可以只读取代码的明确意图 ,即删除满足给定条件的项目。


PS :您可能还想阅读: “如何从STL容器中擦除元素?”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM