2012-01-07 36 views
3

[編輯2]這可能是因爲表面被釋放,而其他對象仍然在使用它...所以我想寫它,所以只有當屏幕上沒有更多的對象時才釋放它。如何防止在for循環中刪除矢量中的對象時發生分段錯誤?

[編輯] [更新]我修復了使用迭代器的代碼,並且我仍然遇到同樣的問題......我只是確認這是該對象的析構函數的問題。在類中析構函數調用SDL_FreeSurface(image);從內存中釋放對象的圖像......但使用複製構造函數創建的對象顯然不適用於此。我需要做些什麼才能使它與使用複製構造函數創建的對象正常工作?我似乎無法在Google上找到與此相關的任何內容。

數字指的是在給定的時間在屏幕上的子彈的數量...我有一個矢量對象「子彈」(矢量項目符號;)...代碼檢查是否觸發按鈕(z)是如果是的話,向下添加一個新的子彈。然後它更新(移動,blits),然後檢查子彈是否在屏幕的末端......一切正常工作,直到子彈到達屏幕末端,它應該被銷燬。

if (trigger) 
{ 
    bullet.push_back(Bullet(position.x, position.y)); 
    ++number; 
} 

for(int i = 0; i < bullet.size(); i++) 
{ 
    bullet[i].update(); 
} 

下面是其中的問題是什麼?當子彈對象被刪除,程序段故障退出......現在,我明白爲什麼會這樣,因爲雖然它在矢量大小改變循環,但我無法弄清楚如何解決它......我添加了休息時間,認爲它可以解決問題,因爲無論如何只有一個子彈可以在給定的時間< = 0,但它不會。 。我最初在更新函數後的最後一個for循環中有if語句,但我把它放在它自己的循環中,這樣我就可以使用break。

for(int i = 0; i < bullet.size(); i++) 
{ 
    if (bullet[i].position.y <= 0) 
    {  
    bullet.erase(bullet.begin() + i); 
    --number; 
    break; 
    } 
} 

我是新來的載體,所以請容忍我在這裏,如果我不明白的東西,或者如果我正在做的n00b錯誤。

+0

的問題在你的代碼是的'erase'後'i'變化的意義。你有一個函數,假定矢量的對象位置對於調用改變這些位置的函數的函數的生命週期是恆定的。 – 2012-01-07 01:57:36

+0

關於編輯和複製構造函數,請閱讀[C++ FAQ:什麼是三項規則?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-ree) – 2012-01-07 04:42:48

+0

謝謝。 ..幫助。 – user1122136 2012-01-07 04:55:42

回答

11

標準擦除循環的序列容器是這樣的:

for (std::vector<Bullet>::iterator it = v.begin(); it != v.end() /* not hoisted */; /* no increment */) 
{ 
    if (delete_condition) 
    { 
     it = v.erase(it); 
    } 
    else 
    { 
     ++it; 
    } 
} 

使用迭代器比使用計數指標可取的,因爲它釋放從櫃檯算術你的代碼添加無關的清晰度代碼並且非常麻煩,而這裏提供的迭代器版本是相當不言自明的。

關鍵不是在發生erase時增加循環變量。

你可能也想看看在remove/erase成語:

v.erase(std::remove_if(v.begin(), v.end(), 
         [](Bullet & b) -> bool { return delete_condition }), 
     v.end()); 
+0

還有點早,只能提供一個C++ 11的答案恕我直言 - – 2012-01-07 01:58:28

+0

@AdrianCornish:lambda被簡單地轉換成拼寫出來的函數/函子,就像'auto'被拼寫輸出類型名稱所取代。那些實際上只是印刷簡寫。你可以感激我沒有說'汽車它(STD ::開始(V))';-) – 2012-01-07 01:59:36

+0

微不足道,當你有標準,並已編程多年:-)就像我說的IMHO – 2012-01-07 02:00:59