2016-03-28 22 views
0

Sınıfımda, for döngüsünü kullanarak std::vector öğesinden bir öğeyi kaldırmaya çalışıyorum. Ancak, elemanı kaldırmaya çalıştığımda bir hata alıyorum ve nasıl çözeceğimi tam olarak bilmiyorum. Elde hatadır:Öğeleri vektörü konumuna göre silinsin mi?

Hata 4 hata C2679: ikili '+': bir operatörün * Düşman 'tipte bir sağ işlenen alır (ya da kabul edilebilir bir dönüşüm vardır)

olan bulundu
void Enemy::UpdateEnemies(SDL_Renderer * render) 
{ 
    for (int i = enemies.size() - 1; i >= 0; i--) 
    { 
     enemies[i]->Update(); 
     if (enemies[i]->Active == false) 
     { 
      // Receive the error here 
      enemies.erase(enemies.begin() + enemies.at(i));    
     } 
    } 
    if ((SDL_GetTicks()-prevSpawnTime)/1000.0f > enemySpawnTime) 
    { 
     prevSpawnTime = SDL_GetTicks(); 
     //Add an anemy 
     AddEnemy(render); 
    }  
} 
+0

Sana 'enemies.erase (enemies.begin() + i) anlamına düşünüyorum;' – DimChtz

+0

@DimChtz Lol aldırma. Bunu daha önce denedim ve çalışmamasının nedeni, aktif değişkeni ilan ettiğimden, ancak hiçbir zaman başlatmamış olmadı. Benim kötü ama teşekkürler. – RoundSquare

cevap

1

Diğer cevaplar size naif çözüm verdik. Ancak, kaldırılacak birden fazla düşmanınız varsa, daha iyi bir çözüme ihtiyacınız vardır. Bu örnekte <algorithm> numaralı telefondan std::remove_if kullanmak daha iyi olurdu. Bu, vektörünüzdeki öğelerin tekrar tekrar karıştırılmasını önleyecektir. Kaldırmak istediğiniz tüm öğeleri, kapsayıcının son sonuna taşıyarak çalışır ve ardından bunların başlangıcına bir yineleyici verir.

auto removed_iter = std::remove_if(enemies.begin(), enemies.end(), 
            [](const Enemy * e) { return e->IsActive(); }); 

enemies.erase(removed_iter, enemies.end()); 

Bu durumda, önce tüm düşmanlarınızı güncellemeniz gerekir. o zaman, ters sırada yapılması gereken yoksa:

for(auto e : enemies) e->Update(); 
+1

Yukarıda, genel olarak gidilecek yol budur. – vsoftco

+0

Bu kodun C++ 11 için olduğunu unutmayın. Bu günleri söylemek zorunda olmamalı, ama bazı insanlar hala eski derleyicileri kullanıyor. Ayrıca, “const Enemy *” ı geçtiğim gerçek, “Enemy :: IsActive” ı const-doğruluğu ile uyguladığınızı gösterir. Derleme hataları varsa, bunu düşünün. – paddy

2

Eğer i-inci elemanı kaldırmak istediğinizi varsayarsak,

enemies.erase(enemies.begin() + i); 

veya daha iyi

yapmanız gereken
enemies.erase(std::next(enemies.begin(), i)); 
yani tip Enemy bir elemanının pozisyonunda i de dereferenced yineleyici döndürür enemies.at(i) daki durumda,

, ve i veya pozisyon i için iterasyon.

daha iyi bir yol ters yineleyicileri kullanmaktır:

for(auto it = enemies.rbegin(); it != enemies.rend(); ++it) 
{ 
    (*it)->Update(); 
    if ((*it)->Active == false) 
    { // need `base()` to convert to regular iterator, then substract 1 
     enemies.erase(std::prev(it.base())); // remove the current position 
     /* or, equivalently 
     enemies.erase(std::next(it).base()); 
     */ 
    } 
} 
0

Bu hat:

enemies.erase(enemies.begin() + enemies.at(i)); 
  • enemise.at, (i) vektörü içinde depolanır Düşman döndürür. hata işaretçi ve vektör eklemeye çalıştığınız, söylediği gibi
  • enemies.begin() bir işaretçi

olduğunu.

Muhtemelen sadece aramak istediğiniz:

enemies.erase(enemies.begin() + i); 
0

Başkalarının söylediklerini ek olarak, bir adım daha ileri götürün ve bir döngü içinde bir vektör gelen silme tanımlanmamış neden olabilir öneririm davranışı. Bir ara göremiyorum, bu yüzden birden fazla inaktif düşmanın olabileceğini farz ediyorum. Kendi döngüsünü yazmak yerine, std :: remove_if algoritmasını kullanmayı düşünün. Esasen kodunuz, derleme yapamayacak bir nesne referansıyla bir yineleyici eklemeye yönelik bir girişimdir. Remove_if çözümü, esasen diğer her şeyi ileriye doğru kaydırırken, Active == false öğesinin kapsayıcının sonuna kadar tüm düşmanları kopyalayacaktır.İlk olarak kaldırılacak şeyleri tanımlamak ve ardından hepsini bir kerede silmek için uygun bir yol sağlar. Ayrıca, bir C++ 11 derleyiciniz yoksa, farklı bir tür yüklemeyi kullanırsanız aynı şey çalışır. Remove_if bağlantısı bir işlevin bir örneğini içerir, ancak bir functor da kullanabilirsiniz.

enemies.erase(std::remove_if(enemies.begin(), enemies.end(), [](const Enemy* e){ return e->Active == false; }), enemies.end()); 

Daha fazla bilgi için şu adrese bakın.

What is a lambda expression in C++11?

http://www.cplusplus.com/reference/algorithm/remove_if/

C++ Functors - and their uses

İlgili konular