简体   繁体   English

指针元素删除传染媒介

[英]Vector of pointers element deletion

I have a vector of pointers and I want to delete an entry. 我有一个指针向量,我想删除一个条目。 After I delete the entry, I check the size of the vector and it is not reduced. 删除条目后,我检查向量的大小,并没有减少。 Should I do an extra thing? 我应该多做一件事吗?

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

Your call to delete *it merely deletes the object pointed to by that entry in your vector. 您对delete *it调用仅删除向量中该条目指向的对象。 You do not modify the vector itself. 您不修改矢量本身。

To also remove the element from the vector, make use of the erase method: 要从向量中删除元素,请使用erase方法:

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

Note that erasing invalidates the current iterator, so you will probably want to assign the return value of the erase call to your it variable. 请注意,擦除会使当前迭代器无效,因此您可能希望将erase调用的返回值赋给it变量。 Be careful not to accidentally skip elements when erasing more than one entry in a loop though. 在删除循环中的多个条目时,请注意不要意外跳过元素。 The returned iterator will point to the element after the one that was deleted and will get incremented again by the for loop. 返回的迭代器将指向已删除的元素之后的元素,并将通过for循环再次递增。

The easiest way to get rid of this issue is to use an STL algorithm for removing the elements instead. 解决此问题的最简单方法是使用STL算法来删除元素。 This works best if the entries also have ownership of their pointees, so you might want to consider using vector of smart pointers instead (as suggested in the comments ), so you don't have to worry about explicitly calling delete at all. 如果条目也拥有其所有者的所有权,那么这种方法效果最好,因此您可能需要考虑使用智能指针向量(如注释中所示 ),因此您根本不必担心显式调用delete

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

After delete *it : delete *it

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

You also need to somehow erase the pointer element in your vector. 您还需要以某种方式擦除向量中的指针元素。 Keep in mind that you can't do erase(it) during the iteration since it invalidates your iterator. 请记住,在迭代期间不能erase(it) ,因为它会使迭代器失效。

You are only freeing memory allocated under the pointer. 您只释放指针下分配的内存。 You're not removing the pointer itself. 你没有删除指针本身。

After you call delete, set the value of pointer to NULL. 调用delete后,将指针值设置为NULL。 After your for loop use std::remove_if with NULL check on elements. 在for循环之后使用带有NULL的std::remove_if检查元素。

Deleting the object will not remove the pointer to it from the vector, it will only free the memory pointed to by the pointer. 删除对象不会从向量中删除指向它的指针,它只会释放指针指向的内存。 You will need to explicitly call erase on the vector after the element is freed. 在释放元素后,您需要在向量上显式调用erase

Having an STL container (eg std::vector ) of owning raw pointers is in general a bad idea. 拥有一个拥有 原始指针的STL容器(例如std::vector )通常是一个坏主意。 This can be a source of leaktrocity : eg if an exception is thrown somewhere, the vector destructor is called, but that will not delete the raw owning pointers! 这可能是泄漏的来源:例如,如果在某处抛出异常,则会调用向量析构函数,但这不会删除原始拥有指针! So their associated resources are leaked. 因此他们的相关资源被泄露了。
Moreover you have to provide explicit cleanup code, etc. 此外,您必须提供明确的清理代码等。

You may want to either use std::vector<Object> , or a std::vector of smart pointers , eg vector<shared_ptr<Object>> or vector<unique_ptr<Object>> (the latter available since C++11 thanks to move semantics, and a good solution if the vector is the unique owner of the objects, and there is no shared ownership). 您可能想要使用std::vector<Object>智能指针std::vector ,例如vector<shared_ptr<Object>>vector<unique_ptr<Object>> (后者可用,因为C ++ 11谢谢移动语义,如果vector是对象的唯一所有者,并且没有共享所有权,那么这是一个很好的解决方案。

You may also want to use algorithms like remove_if() . 您可能还想使用remove_if()算法 In particular, to remove items satisfying some precise condition from vector , you may want to use the so called erase-remove idiom : 特别是,要从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());

The make the code clearer (especially if one doesn't know/recognize the erase-remove idiom), it's possible to write a little helper function to implement this idiom: 使代码更清晰(特别是如果一个人不知道/识别擦除 - 删除习语),可以编写一个小帮助函数来实现这个习惯用法:

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

And then call it like this: 然后像这样调用它:

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

Note that thanks to the use of the remove_if algorithm and the erase-remove idiom, the semantic level of your code is raised: you don't read explicit for loops and iterator incrementing anymore; 请注意,由于使用了remove_if 算法和erase-remove习惯用法,因此提高了代码的语义级别 :您不会读取显式for循环和迭代器递增; you can just read the clear intent of the code, ie erasing items that satisfy a given condition. 你可以只读取代码的明确意图 ,即删除满足给定条件的项目。


PS : You might also want to read: "How do I erase elements from STL containers?" PS :您可能还想阅读: “如何从STL容器中擦除元素?” .

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

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