0

私は夏のプロジェクトとして小さなゲームエンジンを書いていますが、STLマップに少し苦労しています。

RenderListオブジェクトを保持するクラスを宣言しました。RendererRenderListは、作業を行うためにクラスに渡されます。

RenderListがありますmap<std::string,Entity*> objects;

Entity*マップからを取得しようとして、次のようになるまでは、すべて機能します。

vc / include / xtree式でアサーションが失敗しました:マップ/セットイテレータは参照解除できません。

これは、ポインタを取得するためのコードです。

Entity* RenderList::getByName(std::string str){
    return objects.find(str)->second;
}

必要なサブクラスが異なるため、実際のオブジェクトではなく、ポインターを保持するためにEntity必要です。

私はSTLにかなり慣れていませんが、ポインターをマップに格納するべきではありませんか?

確かに私はこれを許可されるべきですか、それとも代わりにオブジェクトを保存する方が良い考えですか?

そして最後に、私は単にそれを間違っているのですか!?

この質問が重複していないことを願って、私は事前にクイック検索を行いました。また、これがGameDev Stackでより良い場合は、そこに投稿します。

4

5 に答える 5

8

キーが見つからない場合map::find(key)は、「過去の最後」のイテレータ、つまり、によって返される値を返します。map::end()そのイテレータはどの要素も指していないため、逆参照できません。find逆参照する前に、何が返されるかをチェックしません。

それらのキーがマップにあることを確認しますか?

キーが見つからない場合は、おそらくNULLを返すようなことをしたいと思うでしょう。これは、返されたイテレータをendegと比較することで確認できます。

Entity* RenderList::getByName(std::string str){
  map_type::iterator it = objects.find(str);
  if (it == objects.end())
    return NULL;
  return it->second;
}

RenderListtypedefを定義する場所:

typedef map<std::string,Entity*> map_type;

(注:実装の詳細として使用するコンテナーのtypedefをクラスで定義するようにしていますmap_type::iterator。これは、コンテナーを他のコンテナーに変更する場合よりも記述がはるかに簡単でmap<std::string,Entity*>::iteratorあり、コンテナーを使用してすべてのコードを変更する必要がないためですmap<std::string,shared_ptr<Entity>>::iterator。そのままにしておくことができますがmap_type::iterator、それでも完全に機能します。)

一般的なデザインに関して、生のポインターの代わりに、boost::shared_ptr<Entity>またはを保存できますか?std::tr1::shared_ptr<Entity>オブジェクトの存続期間を管理する方がはるかに安全で簡単です。

于 2012-07-09T20:55:00.843 に答える
3

それはおそらくあなたが探していた名前が地図に存在しないことを意味します。キーが存在しない場合、findメソッドはマップの終了イテレータを返しますが、これは実際には参照解除できません。

「見つからない」状況が自然に発生する可能性がある場合は、これを行うことができます

Entity* RenderList::getByName(std::string str){
    map<std::string,Entity*>::iterator it = objects.find(str);
    return it != objects.end() ? it->second : NULL;
}

したがって、この状況を処理する責任を発信者に渡します。

「見つからない」状況が発生するはずがない場合は、例外をスローするか、少なくとも実行してください。

assert(it != objects.end());
于 2012-07-09T20:54:53.907 に答える
1

他の人が指摘しているように、あなたが探している名前は地図に存在しません。の戻り値を確認することを誰もがすぐに提案します.find()。代わりに、を呼び出さないことをお勧めします.find()。これが私があなたの問題を解決する方法です:

Entity* RenderList::getByName(std::string str){
  return objects[str];
}

上記のコードでは、存在しないマップエントリを検索すると、NULLポインタ値を持つエントリが作成され、NULLが返されます。

あなたはそれを尊重する前にnullポインタをチェックするためにどこかにいくつかのコードを追加する必要があります。

于 2012-07-09T20:57:45.903 に答える
1

これの1つの問題は、に一致するエントリがない場合を処理する必要があることですstr。ただし、(残念ながら)同じようにマップにディップしてポインタを取得したため、特定のエラーが何であるかはわかりません。

于 2012-07-09T20:55:24.387 に答える
1

メソッドに渡したキーがマップに含まれていない場合は、findを返しobjects.end()ます。これを逆参照すると実行時エラーになり、表示されるエラーが発生する可能性があります。代わりに試してください:

map<std::string,Entity*>::iterator findIt;
findIt = objects.find(str);

if ( findIt != objects.end() )
{
    return findIt->second;
}
else
{
   // Handle error here
}
于 2012-07-09T20:56:30.813 に答える