2010-09-23 89 views
19

我想刪除矢量的內容,我得到一個錯誤 - 矢量迭代器不可遞增,爲什麼?爲什麼這個向量迭代器不可遞增?

這是我的析構函數:

City::~City() 
{ 
    vector <Base*>::iterator deleteIterator; 
    for (deleteIterator = m_basesVector.begin() ; deleteIterator != m_basesVector.end() ; deleteIterator++) 
     m_basesVector.erase(deleteIterator); 
} 

感謝。

+5

假設'm_basesVector'是'City'的成員,不需要擦除它的元素;它的析構函數即將爲你做。 – 2010-09-23 14:15:21

+3

您知道這不會刪除指針指向的對象。你將不得不調用'delete deleteIterator;'來實現它(如果這是你想要的)。但是,在這種情況下,您應該更喜歡'boost :: ptr_vector'。 – 2010-09-23 14:16:27

+0

請參見[there](http://stackoverflow.com/questions/307082/)。 – Wok 2010-09-23 14:40:29

回答

41

erase使迭代器無效。你不能再使用它了。幸運的是,它返回一個迭代器,您可以使用:

vector <Base*>::iterator deleteIterator = m_basesVector.begin(); 
while (deleteIterator != m_basesVector.end()) { 
    deleteIterator = m_basesVector.erase(deleteIterator); 
} 

或者:

m_basesVector.clear(); 

你負責釋放由矢量指針所指的內存?如果這就是你迭代的原因(你真正的程序有更多的代碼,你沒有顯示,這會釋放循環中的那些對象),然後記住,從矢量開始擦除是一個緩慢的操作,因爲在每一步中,矢量的所有元素都必須向下移動一個地方。更好的辦法是循環釋放所有的矢量(然後clear()矢量,儘管如Mike所說,如果矢量是被銷燬的對象的成員,則不需要)。

+0

先循環+1,清除後。 – 2010-09-23 14:20:37

11

問題是,您正在嘗試在使用erase()函數時使用迭代器。 erase(),push_back(),insert()和其他修改函數使STL中的迭代器失效。

只需使用clear()函數:

City::~City() 
{ 
    m_basesVector.clear(); 
} 
+0

那麼,他們是否使迭代器無效取決於容器類型。 – mkb 2010-09-23 14:14:28

+0

@Matt,它不依賴於使用矢量。 – riwalk 2010-09-23 14:18:46

+1

@Matt:'erase'將始終使引用擦除元素的迭代器無效。 – 2010-09-23 14:19:42

0

矢量迭代器是遞增的,但如果你刪除元素,向量內容被修改,因此迭代器是無效的。

所以,如果你刪除對象,你應該使用erase()的返回值,給你下一個有效的迭代器。

1

任何指向已刪除元素或刪除元素後面的元素的迭代器在向量的擦除方法被調用時都會失效。擦除方法返回一個有效的迭代器,指向向量中的下一個元素。您應該使用該迭代器繼續循環,不會增加失效的迭代器。您也可以使用clear方法刪除矢量中的所有元素。但是,您需要記住明確地爲元素分配任何分配的內存。

3

如果你想免費的矢量數據,這樣做:

for (std::vector<Base*>::iterator it = v.begin(), e = b.end(); it != e; ++it) 
    delete *it; 
1

此代碼泄漏向量的所有內容 - 你在循環必須delete *deleteIterator了。您可以通過使用Base而不是Base*作爲vector內容來避免所有這些,然後clear()將爲您破壞它們。或者使用boost::ptr_vector,如果您確實需要原始指針,它會自動銷燬。

在這樣的前向迭代中調用erase()如果vector很大,可能會非常昂貴,因爲當前位置上的每個元素必須向下移動以確保元素保持連續。出於這個原因和其他原因,避免手動清除你建議的類型。

2

發佈這只是incase其他人有這個問題,並試圖解決這個問題,爲什麼它不工作這裏是一個實際的解決方案/解釋。

@Steve Jessop - 你的代碼有缺陷,你也寫在這裏...(我也編輯了他的帖子,一旦它被批准就修復問題,它將被固定在原始文章中)

http://techsoftcomputing.com/faq/3779252.html

我看不出這是一個「解決方案」的問題時,通過做一個無限循環創建一個新的問題,應該有一個deleteIterator ++ while循環中,使得它實際上到達矢量的結尾。

此外,我遇到了這個問題,我的解決方案是在while循環中檢查迭代器是否等於結束,或者如果向量大小是0並且在嘗試遞增迭代器之前斷開。

Ex。

std::vector<RankPlayer*>::iterator Rank_IT = CurrentPlayers.begin(); 

    while (Rank_IT != CurrentPlayers.end()) 
    {  
     RankPlayer* SelPlayer = (*Rank_IT); 

     if(strstr(SelPlayer->GamerTag, this->GamerTag) != NULL) 
     { 

      delete[] SelPlayer->PlayerData; 
      delete[] SelPlayer; 
      Rank_IT = CurrentPlayers.erase(Rank_IT); 
     } 

     if(Rank_IT == CurrentPlayers.end() || CurrentPlayers.size() == 0) 
     { 
      break; 
     } 
      ++Rank_IT; 
    } 
+0

這是一個答案和一個咆哮,以及評論。我強烈建議不要咆哮和評論,否則會很快被刪除。 – 2011-09-02 18:11:28

2

這與上面發佈的原始問題沒有關係,但Google上的搜索錯誤帶我到這個頁面,所以我在這裏發佈它供任何人查看。

我最近遇到了這個錯誤信息,並檢出了所有的代碼行(沒有'擦除'或任何類似的東西;只讀了向量)。

最終,我意識到嵌套循環存在問題。

例如,請考慮這樣的事情: - (!)

`for (it=begin(); it!=end();i++) 
{ 
    for (; it!=end();i++) 
    { 
    } 
}` 

當您使用嵌套的循環中完成,它會遞增迭代器,然後,父循環將再次增加它,最終使迭代器遍歷end()。即如果有這樣的事情,它會是「end()+ 1」。 因此,父循環在下次檢查時引發此錯誤。

要解決這個問題,我結束了插入該行的孩子後循環:

`if (it == vStringList.end()) --it;` 

骯髒的,但工作原理:d

我知道這可能會明顯一些,但我一直在撓我的頭一陣子,lol