2017-01-07 12 views
0

iterate vector, remove certain items as I goの重複ではありません。その問題で使用されたソリューションを試してみました。ベクトルからの消去時のC++セグメンテーションエラー

私は、ゲームオブジェクトのベクトルを持つ「シーン」というクラスがあるゲームエンジンを作っています。

シーンには「destantiate」という機能があり、ゲームオブジェクトを「削除」するために使用する必要があります。

この関数を呼び出すと、std :: vector :: erase関数を使用しようとするとSegmentationフォールトが発生します。

私はそれがベクトルを反復する別のループと関係があるかもしれないと思うし、消去されたベクトルのポインタにアクセスしようとしていますか?

#include "Scene.h" 
#include "Instance.h" 


Scene::Scene() { 
    this->camera = new Camera(0, 0); 
} 

void Scene::instantiate(Instance *instance) { 
    this->instances->push_back(instance); 
} 

void Scene::destantiate(Instance &instance) { 
    instance.trash = true; 
} 

void Scene::tick(float delta) { 
    this->camera->tick(delta); 
    for(std::vector<Instance*>::iterator it = this->instances->begin(); it != this->instances->end(); ++it) { 
     if ((*it)->trash) { 
      std::vector<Instance*>::iterator position = std::find(
      this->instances->begin(), 
      this->instances->end(), 
      (*it) 
      ); 

      if (position != this->instances->end()) { 
       this->instances->erase(position); 
      } 

      continue; 
     } 
     (*it)->collisionBox->width = (*it)->sprite->getCurrentImage()->getWidth(); 
     (*it)->collisionBox->height = (*it)->sprite->getCurrentImage()->getHeight(); 
     (*it)->tick(delta); 
    } 
} 

void Scene::draw(float delta) { 
    this->camera->draw(delta); 
    for(std::vector<Instance*>::iterator it = this->instances->begin(); it != this->instances->end(); ++it) { 
     if ((*it)->trash) { continue; } 
     glPushMatrix(); 

     if ((*it)->centeredOrigo) { 
      glTranslatef((*it)->x - (*it)->sprite->getCurrentImage()->getWidth()/2, (*it)->y - (*it)->sprite->getCurrentImage()->getHeight()/2, 0.0f); 
     } else { 
      glTranslatef((*it)->x, (*it)->y, 0.0f); 
     } 

     if ((*it)->centeredOrigo) { 
      glTranslatef(((*it)->sprite->getCurrentImage()->getWidth()/2), ((*it)->sprite->getCurrentImage()->getHeight()/2), 0); 
     } 

     glRotatef((*it)->rotation, 0.0f, 0.0f, 1.0f); 

     if ((*it)->centeredOrigo) { 
      glTranslatef(-((*it)->sprite->getCurrentImage()->getWidth()/2), -((*it)->sprite->getCurrentImage()->getHeight()/2), 0); 
     } 

     (*it)->draw(delta); 

     glPopMatrix(); 
    } 
} 

のstd ::ベクトル::消去機能は、オブジェクトが「ゴミ」フラグを持っている場合、それはチェックする「ダニ」機能で呼び出されている:

は、以下のコードを見てみましょう。

「destantiate」機能は、ゲームオブジェクトのクラスの内、実行時に呼び出されている場所です:

#include "SDLOpenGL.h" 
#include "TestObj.h" 


TestObj::TestObj(float x, float y) : Instance(x, y) { 
    this->sprite->addImage(game.loader->load("assets/card.png")); 
    this->centeredOrigo = true; 
} 

void TestObj::tick(float delta) { 
    if (this->trash) { return; } 
    //this->x = game.getMousePosition().x; 
    //this->y = game.getMousePosition().y; 
    this->rotation += 2.0f; 

    if (game.keyboardDown(SDL_SCANCODE_LEFT)) { 
     this->x -= 9.5f; 
    } 
    if (game.keyboardDown(SDL_SCANCODE_RIGHT)) { 
     this->x += 9.5f; 
    } 
    if (game.keyboardDown(SDL_SCANCODE_UP)) { 
     this->y -= 9.5f; 
    } 
    if (game.keyboardDown(SDL_SCANCODE_DOWN)) { 
     this->y += 9.5f; 

     //Segmentation fault 
     game.getCurrentScene()->destantiate(*this); 
    } 
} 

void TestObj::draw(float delta) { 
    if (this->trash) { return; } 

    this->sprite->draw(delta); 
    this->collisionBox->draw(delta); 
} 

出力:

Segmentation fault: 11 

そしてValgrindのは、初期化されていないの使用」について何かを言いますポインタ "

+0

はい、反復処理中にベクトルを変更することはできません。しかし、あなたはそのようなごみ箱を持ってはいけません。おそらく、削除すべきオブジェクトを格納する第2のベクトルが必要です。もう一つの選択肢は、ベクターのコピーを操作することですが、私はそれをお勧めしません。 – torkleyy

+0

あなたは[this](http://stackoverflow.com/questions/1604588/iterate-vector-remove-certain-items-as-i-go/1604632#1604632)を試しましたか? – torkleyy

+0

@ User9182736455削除する必要があるオブジェクトを格納するhmm興味深いと思います。 しかし、私はそれを反復して( "delete-vector")、主ベクトルから物を削除しているとしましょう。メインベクタ・ブレイクを反復し、セグメンテーション・フォルトを引き起こすイテレータはありませんか? –

答えて

1

私はあなたが誤っていると思います。コードで説明しようとします:

void deinstantiate(GameObject go) { 
    flaggedForDeletion.push_back(go); 
} 

void tick(float delta) { 
    for(auto it = gameObjects.begin(); it != gameObjects.end(); ++it) { 
     it->tick(delta); 
    } 

    for(auto it = flaggedForDeletion.begin(); it != flaggedForDeletion.end(); ++it) { 
     std::remove(vec.begin(), vec.end(), *it); 
    } 
} 

したがって、削除するオブジェクトを保存して後で削除するだけです。イテレータを無効にするため、反復処理中は削除できません。

thisを除き、ソリューションはあなたに適しています。

+0

これは私の問題を解決しました!ありがとう! :D –

+0

https://github.com/sebbekarlsson/Scenengine/commit/b868d338330289d2198a6da750308fa1b77fc64a –

関連する問題