2015-04-17 131 views
0

我一直在努力把一個矢量對象放到一個項目中,我正在做 我已經閱讀了我能找到的關於做這件事的一點點,並決定放棄它。C++矢量對象.erase

 std::vector<BrickFalling> fell; 
     BrickFalling *f1; 

我創建了這個向量。這下一件工作正常,直到我到 擦除部分。

if(brickFall == true){ 

f1 = new BrickFalling; 

f1->getBrickXY(brickfallx,brickfally); 

fell.push_back(*f1); 
brickFall = false; 
} 
// Now setup an iterator loop through the vector 

vector<BrickFalling>::iterator it; 

for(it = fell.begin(); it != fell.end(); ++it) { 

    // For each BrickFalling, print out their info 

    it->printBrickFallingInfo(brick,window,deadBrick); 

    //This is the part im doing wrong ///// 
    if(deadBrick == true)// if dead brick erase 
    { 
     BrickFalling[it].erase;//not sure what im supposed to be doing here 
     deadBrick = false; 
    } 
} 
+4

這看起來不是一個使用'new'的好地方。我的錢就是在泄露這個對象。 – chris

回答

3

只要有可能,應該使用詳細說明使用remove_if的其他答案。但是,如果您的情況不允許使用remove_if編寫代碼(可能發生在更復雜的情況下),則可以使用以下代碼:

您可以使用vector::erase和迭代器刪除該位置處的元素。所使用的迭代器將失效。 erase返回一個指向下一個元素的新迭代器,因此您可以使用該迭代器繼續。

你結束了什麼是一個循環,如:

for(it = fell.begin(); it != fell.end(); /* iterator updated in loop */) 
{ 
    if (shouldDelete) 
     it = fell.erase(it); 
    else 
     ++it; 
} 
+1

'std :: remove_if'已經制作並測試過。如果代碼看起來像這樣,它應該被替換,並可能對結果進行「擦除」。 – chris

+0

這是一個很好的觀點。不是所有的情況都被整齊地寫成'remove_if'後面跟着'erase',所以對於這些(更特殊的情況)我的代碼可以被使用。 – MicroVirus

4

您可以通過使用std::remove_ifvector::erase沿完全避免這個問題。

auto it = 
    std::remove_if(fell.begin(), fell.end(), [&](BrickFalling& b) 
       { bool deadBrick = false;  
       b.printBrickFallingInfo(brick,window,deadBrick); 
       return deadBrick; }); 

    fell.erase(it, fell.end()); 

這可以避免手寫循環。

一般來說,您應該努力以這種方式爲順序容器編寫擦除循環。原因在於,在自己編寫循環時進入「無效迭代器」場景非常容易,即每次擦除完成時都不記得重置循環迭代器。

您不知道的代碼的唯一問題是printBrickFallingInfo函數。如果它throws是一個例外,你可能會在擦除過程中引入一個錯誤。在這種情況下,您可能需要使用try/catch塊來保護呼叫,以確保您不會太早離開功能塊。

編輯:

正如評論所說,你print...功能可以做太多的工作只是爲了確定是否磚下降。如果你真的試圖印刷東西,並做更多的事情,可能造成某種副作用,另一種類似性質的方法是使用std::stable_partition

隨着std::stable_partition可以「擱置」擦除,只是移動元素在容器中的一個位置(或者開頭或結尾)被刪除所有,同時又不會使這些項目。這是主要區別 - 與std::stable_partition,你所做的只是移動要處理的項目,但移動後的項目仍然有效。 std::removestd::remove_if不是這樣 - 移動的項目只是無效的,任何嘗試使用這些項目就好像它們仍然有效是未定義的行爲。

auto it = 
    std::stable_partition(fell.begin(), fell.end(), [&](BrickFalling& b) 
       { bool deadBrick = false;  
       b.printBrickFallingInfo(brick,window,deadBrick); 
       return deadBrick; }); 

    // if you need to do something with the moved items besides 
    // erasing them, you can do so. The moved items start from 
    // fell.begin() up to the iterator it. 
    //... 
    //... 
    // Now we erase the items since we're done with them 
    fell.erase(fell.begin(), it); 

的此不同的是,該項目我們將最終擦除會騙分區迭代器it的左側,所以我們erase()通話將刪除從頭開始的項目。除此之外,這些項目仍然是完全有效的條目,因此您可以在最終刪除它們之前以任何方式使用它們。

+0

只是想添加一個小小的提示,稱爲「print ...」的函數似乎正在改變'deadBrick'。看起來它做得太多了,至少應該分成「print ...」和「isDeadBrick」。 – chris