なぜとがないのかは理解できますが、なぜとがないのかoperator==疑問に思います。特に、の参照を介してを作成できるためです。私はあなたが望む時間の99%のために仮定します。誰かが私に正当な理由を挙げられない限り、私は先に進んでそれを私のコードに導入します。なぜそのようなことをすべきではないのですか。shared_ptrunique_ptrshared_ptrweak_ptrweak_ptrshared_ptrlhs.get() == rhs.get()
3 に答える
weak_ptr基になるポインタにアクセスする前にget()を明示的にロックする必要があるため、にはメソッドがありません。weak_ptrこれを明示的にすることは、意図的な設計上の決定です。shared_ptr変換が暗黙的である場合、オブジェクトから取得された基になるポインターweak_ptrがまだ調べられている間にオブジェクトの最後のものが破棄された場合に安全でないコードを書くことは非常に簡単です。
このブーストページには、落とし穴と、なぜweak_ptrそのような制限されたインターフェイスがあるのかについての適切な説明があります。
簡単な比較を行う必要がある場合は、を行うことができますshared == weak.lock()。比較が真の場合、同じオブジェクトにweak別のものを持っているので、それはまだ有効でなければならないことがわかります。shared_ptr比較がfalseを返した場合、そのような保証はありません。
コストがかかるからです。
Aweak_ptrはオブザーバーのようなものであり、実際のポインターではありません。shared_ptrそれを使って作業を行うには、最初にそのlock()メソッドを使用してそれからを取得する必要があります。
これには所有権を取得する効果がありますが、通常のコピーshared_ptr(カウントの増分など)と同じくらいコストがかかるため、簡単なことではありません。
そのため、を提供しないことにより==、あなたは一歩下がって、本当にこれが必要かどうかを実際にチェックすることを余儀なくされます。
他の回答が指摘しているように、基礎となるポインタを単純に比較することは危険です。1つは、次のシナリオを考えてみます。オブジェクトへの弱参照Aが存在し、その後削除されるため、弱参照が期限切れになります。次に、同じアドレスを持つ、上記の削除によって解放されたメモリに別のオブジェクトが割り当てられます。これで、弱いポインタが元々別のオブジェクトを参照していても、基になるポインタは同じになります。
他の回答が示唆しているように、1つの方法はを比較することshared == weak.lock()です。lock()弱いポインタが期限切れになると(偽のポインタではなく)返されるのでnullptr、彼はそれらが等しいかどうかを識別するために機能します(限りshared != nullptr)。ただし、これには2つの問題があります。
- ウィークポインタが期限切れになると動作を停止します。その場合、比較が変更されます。有効期限が切れると、がtrueの場合にのみtrueが返されます
shared == nullptr。unordered_mapこれは、またはのキーとして使用する場合など、比較を安定させておく必要がある場合に危険unordered_setです。 lock()比較的費用のかかる操作です。
幸いなことに、これを行うためのより良い方法があります。両方ともweak_ptr、制御ブロックshared_ptrと呼ばれるものへのポインタを格納します。これは、参照カウントを格納し、参照が残っている限り元のオブジェクトよりも長持ちします。それらが同じオブジェクトを参照しているかどうかを確認するには、制御ブロックのポインターを比較するだけです。これは、次の方法で実行できます。owner_before
template<class T>
bool owner_equals(std::shared_ptr<T> &lhs, std::weak_ptr<T> &rhs) {
return !lhs.owner_before(rhs) && !rhs.owner_before(lhs);
}
このアプローチは、2つstd::weak_ptrが(一度)同じオブジェクトを参照しているかどうかを知りたい場合は、2つを相互に比較する場合にも機能します。これは、制御ブロックが(少なくとも)すべての弱参照の間続くためです。
のエイリアシング機能を使用している場合、これは期待どおりの結果をもたらさない可能性があることに注意してください。これは、同じ制御ブロックでstd::shared_ptr2つのインスタンスを作成し、それでも異なるポインタを格納できる機能です。std::shared_ptr