2

私は趣味のC++プログラマーであり、これが私の最初の投稿です。

まず、クロスプラットフォームのansiC++に取り組んでいることをお伝えします。

私はちょうどメモリ管理を理解するために多くの仕事をしてきました、そして私はついにstd :: vectorを使用して、削除中に手動でポインタを管理するコツをつかみました。

また、私はboost :: smart_ptrを使用していて、ついにクリックされました。

しかし、コンストラクターがFooManager(シングルトン)に自分自身を登録するクラスFooがあるコードに出くわしました。

Foo::Foo()
{
 FooManager::Instance()->register(this);
}

FooManagerの破棄中に、std :: vectorを繰り返し、各要素に消去と削除を適用して、Fooのメモリを効果的にクリーンアップします。

FooManager::~FooManager()
{
    // iterate over the container of Foo pointers
    // erase the pointer from container and delete the pointer
}

a)作成中にポインタをラップするためにboost :: smart_ptrを使用しておらず、b)コンストラクタとデストラクタでメモリ管理のトリックを使用しているため、混乱しました。

これは実行可能な解決策ですか、それともシングルトンのデストラクタを使用して管理対象のオブジェクトをクリーンアップすることに伴うひどい危険がありますか?

私自身のテストから、1つの根本的な欠点を発見しました。Fooはもうスタックに割り当てられるべきではありません。オブジェクトがスコープ外になると、オブジェクトはそれ自体を逆参照します。FooManagerのデストラクタが呼び出されると、FooManagerはそれを再度削除しようとします。これにより、アサートエラーが生成されます。

_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-> nBlockUse));

それが唯一の欠点ですか?マネージャーへの登録をFooコンストラクターの外に移動する必要がありますか?プログラムの寿命の終わりに手動で呼び出すメモリをクリーンアップするFooManagerの個別の関数が必要ですか?この問題についてどう思いますか?

4

2 に答える 2

0

正直なところ、クラスの設計は少し非対称だと思います。

  1. すべてのFooオブジェクトは、作成時に登録されます。
  2. FooManagerはすべての登録削除し、削除時にすべての登録済みFooオブジェクトを削除します。

問題は、FooManagerがFooオブジェクトを集約しているだけなのか、それともライフサイクルも処理しているのかということです。

  • FooManagerがFooオブジェクトの集計のみを提供している場合、FooManagerはオブジェクトを「所有」していないため、破棄されたときにそれらを削除しないでください。単純な内部登録解除で十分です(注:マルチスレッドプログラムで問題が発生する可能性があります)。

  • FooManagerがFooオブジェクトをより厳密に制御する必要がある場合(つまり、ライフサイクル全体を処理する場合)、ファクトリパターンの方が適切な場合があります。FooManagerのみがFooオブジェクトを割り当てることができます。

于 2012-12-28T22:51:05.087 に答える
0

いくつかの問題があります。

  1. FooMananger のシングルトン インスタンスは静的変数であり、プログラムの最初から最後まで有効期間があります。プログラムの最後でのみ呼び出される可能性のある FooManager のデストラクタで Foo のみを削除すると、メモリ管理はまったく行われません。Foo インスタンスをまったく削除しないのと同じです。ではない?

  2. すでにわかっているように、FooManagerが Foo のコンストラクター内でポインターを登録する方法により、スタックに Foo オブジェクトを割り当てることができなくなります。無効なメモリの場所、または触れてはならない場所を指すポインタになってしまいます。

一般的な方法は、スマート ポインターを使用することです。必要に応じて、boost::shared_ptr、boost::scoped_ptr、std::uniqe_ptr (c++11) などを使用できます。

于 2012-12-28T22:35:01.360 に答える