3

私は現在、2D ゲーム エンジンに取り組んでおり、auto_ptr と、それらを標準コンテナーに入れてはならない方法について読みました。

私のエンジンはこの構造を持っています:

StateManager -- 多くあります --> State です。

状態は、エンジンの外側のメインで作成され、割り当てられます。コマンドで状態を変更できるように、エンジンにすべての状態のリスト/ベクトルを保存してもらいたいです。

例えば:

SomeState *test = new SomeState();
StateManager->registerState(test);

アプリケーションが終了したときにのみ状態が終了するため、このアプローチを使用できますか?

std::auto_ptr<SomeState> test(new SomeState());
StateManager->registerState(test.get());

// Inside StateManager State *activeState; // State manager then maintains a vector std::vector<State*> stateList; // and upon registerState it adds the pointer to the vector void registerState(State *state) { stateList.push_back(test); }

StateManager は、状態へのポインターのベクトルのみを維持する必要があり、所有権を取得する必要はありません。エンジンの状態を変更したい場合は、activeState ポインターを変更して、stateList ベクトルにある目的の状態を指すようにします。

これは悪いアプローチですか?

4

5 に答える 5

9

代わりに std::vector<State> を使用して、ポインターの保存について心配しないのはなぜですか? 状態のリストが固定されているように聞こえるので、プログラムの存続期間中にイテレータが無効になることはありません。

あるいは、Boost Pointer Containerライブラリがこの種の作業に役立つことがわかりました。

于 2010-07-13T11:48:44.587 に答える
4

StateManager は含まれるオブジェクトを所有していないため、その含まれる型はスマート ポインターではなく State* である必要があります。main 関数で auto_ptr を使用しても問題ありません。これは StateManager コンテナーとは関係ありません。

含まれるオブジェクトの有効期間を担当するコンテナーが必要な場合は、含まれる型としてスマート ポインターを使用できます。ただし、auto_ptr はプリミティブな所有権アルゴリズムを使用しているため、これには危険です。そのようなコンテナーでは shared_ptr を使用することをお勧めします。

于 2010-07-13T11:52:03.860 に答える
3

それを妨げるものがない場合 (ポリモーフィズムなど)、最も単純なアプローチ、つまりstd::vector<State>. activeStateポインター (または反復子) にすることもできます。

于 2010-07-13T11:47:06.023 に答える
1

投稿したコードで auto_ptr を使用する方法は機能しません。

std::auto_ptr<SomeState> test(new SomeState());
StateManager->registerState(test.get());

「test」変数がスコープ外になると、そのデストラクタが呼び出され、StateManager に登録した SomeState オブジェクトが削除されます。そのため、StateManager は削除されたオブジェクトへのポインターを保持しているため、途中でクラッシュする可能性があります。

代わりに、 boost::shared_ptrなどの参照カウンター スマート ポインター タイプの使用を検討できます。

于 2010-07-13T11:53:03.027 に答える
0

auto_ptrは、指定されたコンテキスト内でオブジェクトの存続期間を管理することになっています。例えば

void foo(){MyObject * pNewObject = new MyObejct;

//何かを行うdeletepNewObject; }

上記の関数で、// Do Somethingコードで何らかの例外が発生した場合、オブジェクトは解放されず、コードでメモリリークが発生します。このような状況では、Auto_ptrsを使用します。

ただし、次のコンテキスト(配列の解放)には適していません。auto_ptrのデストラクタでは、deleteptrを呼び出します。ただし、配列の場合は、delete[]ptrを呼び出す必要があります。配列でauto_ptrを使用すると、メモリリークが発生し、予期しない動作が発生しますvoid foo(){

unsigned char * pStream = new unsigned char [size]; ...。

delete [] pStream; }

状態があまりなく、メモリにそれほど貪欲でない場合は、状態クラスにシングルトンオブジェクトを使用することをお勧めします。したがって、メモリ管理について心配する必要はありません。状態マネージャーはアクティブな状態と状態オブジェクトを処理できますが、状態マネージャーの外部で状態オブジェクトを初期化し、残りを状態マネージャーなどで行うのは良い考えではないと思います。作成と破壊が統一されていることを確認してください

于 2010-07-13T12:30:03.360 に答える