我有一个指针向量,我想删除一个条目。删除条目后,我检查向量的大小,并没有减少。我应该多做一件事吗?
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());
答案 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::vector
或vector<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?"。