簡體   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