1

スマート ポインターの動作の新しい定義を書き直す可能性については常に読んでいますが、今日でも実際の例を見つけることができません。

今、私はこの問題を提案し、解決策が得られるかどうかを確認したいと思います:

スマート ポインターは、参照カウントまたは参照リンクを使用してライフタイム サイクルを管理しています。私の基本的な問題は、ポインターの解放と削除を引き起こす可能性のある新しい状態を追加することです。イベントがトリガーされたときにリソースを解放したいと考えています。

ゲームをプレイするときとほぼ同じです。通常、ユーザーがレベル 1 からレベル 2 に移行するときにすべてのリソースがロードおよび解放されるため、これが発生すると、レベル 1 のリソースが解放されます。また、自動参照カウントを待つことができないため、この例に固執したいと思います。おそらく、レベル 2 でレベル 1 のリソースが使用されていない場合、それは要求されなくなったため、自動的に解放されます。 ; これは真実かもしれませんが、ユーザーがストレス下でマシンを使用しているときにメモリを操作することは、非常に悪い動きです。

スマート ポインターが提供する他のすべての機能にも興味があるため、スマート ポインターを使い続けたいと思いますが、スマート ポインターには大きな欠点があり、ライフ サイクルを直接的に管理する必要があります。

どのようなオプションがありますか?

4

4 に答える 4

4

たくさんの共有ポインターを投入しただけで、リソースの所有権について適切に考えていないように思えます。説明から、レベル オブジェクトがこれらすべてのリソースを所有する必要があることは明らかです。つまり、それらは共有されるべきではないため、参照カウントはまったく必要ありません。

スマート ポインターを使用すると、リソースを適切なタイミングで手動で解放する負担から解放されますが、適切なタイミングを考える必要はありません。

私が正しく、レベルがリソースを所有する必要がある場合は、一意の所有権を与えるスマート ポインターを使用するか、単に自動オブジェクトを使用し、スマート ポインターを気にしないでください。それらのオブジェクトへのアクセスを必要とするレベルを除く他のすべてのオブジェクトは、それへの非所有ポインターまたは参照、つまり従来のポインターまたは参照を必要とします。

私が間違っていて、リソースを実際に共有する必要がある場合は、レベルが破棄されたときにリソースを解放するべきではありません。所有権を共有していた他のオブジェクトはそれを好まないでしょう。

于 2012-08-12T01:20:25.113 に答える
3

前述のように、特定の問題に対する共有ポインターは適切な解決策ではない場合があります。ただし、たとえば、レベルの解放をタイムスライスしたい場合は、手動で破壊を管理することもできます (または、メモリの負荷が高すぎたり懸念されたりしない場合は、CPU サイクルに余裕があるときに後で待つこともできます)。 )。リソースの処理が完了したら、グローバル キュー (または、タイプごとまたは優先度ごとなど、複数のキュー) で破棄するために単純にキューに入れます。後で、そのキューを処理して参照を削除するだけです。実際にオブジェクトへの最後の参照である場合、これによりオブジェクトの破棄がトリガーされます。たとえば、数回の反復ごとにタイマーを簡単にチェックし、1ms を解放するのに費やしたら、終了して次のフレームに進むことを確認できます。

パフォーマンスに関しては、レベルごと (またはアセット パッケージごと) にメモリ プールを使用する方が理にかなっています。これにより、メモリ管理が容易になり、プール全体を一度に解放して、その中のすべてのオブジェクトのデストラクタの呼び出しをスキップすることができます (何もしないことがわかっている場合)。

于 2012-08-12T02:02:31.180 に答える
3

レベルが終了した後に共有ポインターが残っている場合、それは、共有ポインターがレベルの存続期間中に呼び出される関数のスタックに自動変数として割り当てられず、保存されているためです。ある種のコンテナまたは一連のグローバルにアクセス可能なコンテナで。したがって、考慮する必要がある主な問題は、各レベルのリソースを管理する共有ポインターを含むコンテナーのライフサイクルを管理することです。

たとえば、一部の関数内のスタックに割り当てられたスマート ポインターにfooは、関数呼び出しの期間に対応する寿命しかありません。関数呼び出しが完了すると、共有ポインタは破棄されます。リソースを指している追加の共有ポインターがある場合、リソース自体は破棄されませんが、それらの追加の共有ポインターは、呼び出し先のスタック以外の場所に存在する必要があります。したがって、あなたの仕事は、これらの「他の場所」を管理することです。これは、グローバルにアクセス可能な一連のコンテナーである可能性が最も高いと思います。

したがって、各レベルのデータを管理するコンテナをフラッシュすると、各レベルに割り当てられたリソースが完全に破棄されます。必要に応じて、コンテナーのフラッシュをトリガーするイベント駆動型インターフェイスまたは単純なオブザーバー パターンを使用することも、レベル リソースの有効期間を管理するオブジェクトのデストラクタによって明示的に実行することもできます。

最終的にはリソース管理に行き着きます...共有ポインターがメモリリークを防ぐように設計されているからといって、それらがどのように、またはどこに割り当てられているかを追跡してはならないという意味ではありません。共有ポインタのストレージを集中化すれば、それらが管理するリソースを破棄することはそれほど大したことではありません。

于 2012-08-12T01:18:06.087 に答える
2

共有ポインタをまったく使用すべきではないようです。カスタム デアロケーターを指定して動作をオーバーライドする方法はありますが、別の種類の「スマート ポインター」を検討します。

Apache Web サーバーはメモリ プールを使用して、リクエストにメモリ プールを所有させることで、リクエストに関連付けられたすべてのリソースの割り当てを解除します。サーバー内でメモリを割り当てる場合、割り当て元のプールを特定する必要があります。サーバーは、サーバーインスタンス用、モジュール用、リクエストごとなど、それぞれ異なる寿命を持つ少数のメモリプールを維持します。これは、状況により適しているように思えます。

Apache コードは、メモリ管理にApache Portable Runtimeを使用します。これは C で書かれており、あなたがやっていることには最適ではないかもしれません。Boostにもメモリプールライブラリがあるようですが、使用したことはありません。

于 2012-08-12T01:44:10.777 に答える