10

時々、ポインターの循環依存が必要であり、循環上のすべてのオブジェクトがそのポインターを使用できる必要があると確信している場合があります (したがって、weak_ptr にすることはできません)。

私の質問は、これは私の設計が悪いということですか?

グラフを実装したい場合はどうすればよいですか? スマート ポインターを使用できますか? グラフには循環がありますが、weak_ptr では "->" を使用できません。私に何ができる?

StackOverflow に関するいくつかの記事、リファレンス、およびトピックを読みましたが、まだスマート ポインターを取得していないようです。本当に、「->」を使用したweak_ptrのバリアントが存在しないのはなぜですか?

4

3 に答える 3

30

これには、実装側ではなく、概念側からアプローチしてください。スマート ポインタは所有権を表します。また、スマート ポインターが存在しても、所有していないオブザーバーとしての生のポインターの役割が無効になることはありません。

各オブジェクトには明確に定義された単一の所有者がいますか (たとえば、グラフはそのすべての頂点とエッジを所有していますか)? その場合は、 を使用std::unique_ptrしてグラフ内の頂点とエッジを保持し、頂点とエッジ内で生のポインターを使用して相互に参照します。

所有権の共有は適用できますか (たとえば、頂点は、少なくとも 1 つのエッジが接続されている場合にのみ存在します)? std::shared_ptrその場合は、所有していないオブザーバーの生のポインターを使用して、その所有権を表すために使用します。「頂点はエッジが参照する限り存在し、エッジは頂点が参照する限り存在する」相互所有権 (つまり、所有権サイクル) が必要な場合は、1. そのような設計が2. その場合std::weak_ptrは、サイクルのどこかで a を使用して、所有権のループを断ち切ります。いつでもlock()weak_ptr取得できshared_ptrます。

あなたの特定のグラフシナリオでは、「すべてがグラフによって所有されている」ことが最も論理的な所有権スキームになると思います。しかし、それはあなたの仕事の特異性に依存します。

于 2014-05-01T13:48:22.997 に答える
4

weak_ptrサイクルのどこかで使用できます。weak_ptrs をs にプロモートしてからshared_ptr参照解除する必要があります。これは、 toのコンストラクターを呼び出すweak_ptr::lock()か、単純に渡すことで実行できます(ただし、注意してください。オブジェクトが指すオブジェクトが破棄されている場合、例外がスローされます。weak_ptrshared_ptrbad_weak_ptrweak_ptr

本当にこれができない場合 (たとえば、サイクルに含まれるすべてのオブジェクトが同じタイプである場合、グラフの例ではおそらくそうです)、別のオプションはrelease、チェーンのどこかに関数を配置することです。問題のオブジェクトを呼び出して、そのすべてshared_ptrの を null に設定します。

于 2014-05-01T13:38:37.600 に答える
1

これは私のデザインが悪いということですか?

はい、しかしそれは出発点です。

使用できるスマート ポインターのいくつかを考えてみましょう。

unique_ptr- オブジェクトの処分を担当する単一の所有者が存在します。

shared_ptr- 多くの (または潜在的に多くの) 所有者が存在し、最後の所有者がオブジェクトを破棄する必要がある

weak_ptr- 多くの所有者が存在する可能性がありますが、これはそれらの 1 つではありません。ウィーク ポインターは、指しているオブジェクトが無効になる可能性があります。指しているオブジェクトが破棄された場合、ウィーク ポインターは null になります (つまり、lock メソッドは null の shared_ptr を返します)。

observer_ptr(n3840) - まだ標準の一部ではないため、必要に応じて代わりに C スタイルのポインター (T*) を使用できます。これらはweak_ptrと非常によく似た働きをしますが、指すオブジェクトが破棄された後にすべてのオブザーバーが逆参照されないようにするのはプログラマーの責任です。

解決策は、すべてのピースとピース (サイクル ノード) を所有するオブジェクトにデザインを分割することです。所有するオブジェクトは、shared_ptrまたはを使用unique_ptrして、ノードの寿命を自動的に管理できます。weak_ptrノード自体は、 、observer_ptr、または参照 (Node&) で相互に参照できます。

于 2014-05-02T22:10:56.107 に答える