1

ゲームエンジン用の簡単なイベントマネージャークラスとリスナーを作成しようとしています。通常の実装(つまりMcShaffry)では、イベントマネージャーはリスナーを登録します。これにより、原則として、shared_ptrがプライベートメンバーとしてリスナーに保存されます。

多くの場合、shared_ptrなどは避けるべきだと言われています(例:ここ)。したがって、リスナーの所有権を共有せずにイベントマネージャーを実装する方法を見つけようとしています。

私が考えた方法の1つは、リスナーに一意のIDを割り当て、そのIDをイベントマネージャーに登録することです。次に、リスナーは、イベントマネージャーが更新された後、自分のIDでイベントが利用可能かどうかを、イベントマネージャーに「尋ねる」責任があります。

この場合、共有所有権を回避するためのよりクリーンな方法や標準的な方法があるかどうかを尋ねたいと思いますが、一般的にもそうです。たとえば、リスナーにも同じ問題があります。リスナーは、イベントを処理するときにそのメソッドを呼び出すことができるように、親(またはリッスンしているオブジェクト)へのポインターを格納する必要があります。

4

5 に答える 5

2

shared_ptr過度に使用される傾向があります。たとえば、あいまいに述べられたポインターの問題の解決策として、SO で推奨されることがよくあります。これは優れた設計に代わるものではなく、記述されているコードでオブジェクトの有効期間の問題を理解することに基づいた設計が適切に行われていない限り、使用しないでください。

于 2013-01-10T17:07:01.997 に答える
2

Mat のコメントが言うように、一般的にスマート ポインターを使用しない理由はありません。とはいえ、あなたの状況には警告当てはまるようです。私が理解している限り、あなたは所有権を共有していません。イベント マネージャは、リスナーの唯一の所有権を持っています。shared_ptrしたがって、ここではAは不適切です。

unique_ptr別の方法は、多くの点でshared_ptrコインの反対側にある a を使用することです。ただし、リスナーをモデル化する方法によっては、具体的なインスタンスをイベント マネージャーに保存するだけで回避できます。より詳細な説明がなければ、ポインターがまったく必要かどうかを言うことは不可能ですが、ポインターが必要ない場合は、はい、アドバイスが適用されます。具体的なオブジェクトが必要な場合は、(スマート) ポインターを使用しないでください。

最後に、リスナーが所有権が別の場所で管理されているオブジェクトである場合は、単にそれらのオブジェクトへの生のポインターを使用することを検討してください。その場合、イベント マネージャーはオブジェクトの所有者ではなく、唯一の所有者でも共有所有者でもありません。これは私にとって好ましい方法ですが、リスナーの存続期間を注意深く分析して、イベント マネージャーが存在しないリスナーを指さないようにする必要があります。

于 2013-01-10T17:06:22.137 に答える
1

個人的な経験からshared_ptr言うと、それは素晴らしいことですが、仕事には適切なツールではない場合もあります。コードが完全に自分の管理下にある場合、99.9% の確率でshared_ptr作業が楽になります。次のように考えないようにする必要があります。

Foo *f = new Foo();
shared_ptr<Foo> fptr(f);
shared_ptr<Foo> fptr2(f);

これにより、 f のメモリが または のいずれかで割り当て解除されfptr1ますfptr2。代わりに、次のようなことをしたい:

Foo *f = new Foo();
shared_ptr<Foo> fptr(f);
shared_ptr<Foo> fptr2 = fptr;

2 番目のケースでは、ある共有ポインターを別の共有ポインターに割り当てると、参照カウントがインクリメントされます。

問題が発生する可能性のある別の場所はshared_ptr、ネイキッド ポインターを関数に渡す必要がある場合です (これは、これをメソッドの最初のパラメーターとして渡す必要がある場合、またはサード パーティのライブラリに依存している場合に発生する可能性があります)。からネイキッド ポインターを取得できますshared_ptrが、参照カウンターがインクリメントされないため、ポインターが指しているメモリ アドレスがまだ存在するという保証はありません。

追加shared_ptrの を保持することでこれを回避できますが、これは面倒な場合があります。

他の形式のスマート ポインターがあります。たとえば、OpenSceneGraph にref_ptrは よりも操作しやすい がありshared_ptrます。1 つの注意点は、それが指すすべてのオブジェクトは の子孫でなければならないということReferencedです。しかし、それでよければ、本当に悪いことが起こるのははるかに難しいと思います。

于 2013-01-10T17:08:21.690 に答える
0

場合によってshared_ptrは、やり過ぎであったり、目的のセマンティクスが適切に表示されないことがあります (たとえば、所有権の受け渡しなど)。

必要なことは、デザインを見て、必要な所有モデルを確認することです。所有権の共有が必要な場合は、それshared_ptrをモデル化するために使用してください。共有/参照カウント所有権が適切でない場合は、別のスマート ポインターを使用します。

于 2013-01-10T16:59:34.763 に答える
0

あなたのケースは、ここで説明されている の優れた使用法に適していると思いませauto_ptrか?

私が理解していることは、リスナーを作成してからイベントマネージャーに渡すことです。したがって、イベント マネージャは「シンク」と見なすことができます。

auto_ptr 手法を使用すると、イベント マネージャーは、指定したリスナーの完全な所有権をクリーンかつ安全に取得できます。

于 2013-01-16T13:26:33.873 に答える