[英]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.