C++ のshared_ptr とリソース管理用の unique_ptr
-
21-12-2019 - |
質問
の使用を検討中です unique_ptr
対 shared_ptr
対 own_solution
. 。後者はほぼ確実に間違う可能性があるので無視しましたが、両方とも問題があります unique_ptr
そして shared_ptr
どちらも私が望むものを正確に捉えていないという点で。リソースを明示的に所有するリソース マネージャーを作成したいのですが、リソース マネージャーにはリソースへの参照も配布したいと考えています。
私が使うなら unique_ptr
リソースマネージャーで生のポインターを渡すと、他の場所にエスケープできる可能性があります(ただし、これはクラスの「契約」に違反すると思います)。私が使うなら shared_ptr
そして配る weak_ptr
, 、発信者が変換するのを妨げるものは何もありません。 weak_ptr
に shared_ptr
そしてそれを保存することで、リソース マネージャーの有効期間を超えてリソースが存続するサイクル、またはさらに悪いことが発生する可能性があります。だから私が探しているのは遅延可能だと思います weak_ptr
に変換できないもの shared_ptr
.
それとも、コード内にいくつかの強い言葉のコメントを入れて契約を強制したいだけなのでしょうか?
これについてご意見がございましたら、よろしくお願いいたします。
解決
shared_ptr
およびunique_ptr
のようなスマートポインタは、 Pointersを所有している場合は良いツールです。
しかし、所有のポインタ、すなわち、RAWポインタを使用して、観察ポインタはちょうどいいです。
あなたのデザインでは、リソースマネージャはリソースの唯一の「所有者」であると思います。そのため、内部のスマートポインタを単ににすることもできます。たとえば、Resource Managerは、std::vector<std::unique_ptr<Resource>>
をデータメンバーとして、またはstd::vector<Resource>
クラスがResource
で正しく格納可能になるように設計されている場合は、より単純なstd::vector
さえも使用できます。
その後、リソースマネージャは、所有の非所有のポインタだけで外部に与えることができ、この場合は生ポインタ(またはC ++参照)が大丈夫です。
もちろん、リソースマネージャの有効期間が「リソースクライアント」の有効期間を超えることが重要です。他のヒント
結局のところ、誰かに聞くように強制することはできません。マイクロソフト、アップル、その他のオープン ソース ライブラリの開発者に尋ねてみると、誰もがその曲を知っています。適切な言葉と場所でコメントすることが最善の策です。
独自のスマート ポインター クラスを作成しないでください。作成すると、構成が妨げられ、可読性が低下します。最後の手段として、boost またはコードがすでに動作する必要があるフレームワークを探してみてください。
所有者がいない場合は、所有者として選出されるか、 weak_ptr
s または (有効期間中有効であることが保証されている場合) 生のポインタ。
使用する場合 shared_ptr
内部的には (なぜそうする必要があるのか)、提供するのが最善です weak_ptr
そして生のポインタ。
これらすべてのスマート ポインターは、所有権ポリシーを明示的に示します。生のポインタは、何も存在しないか、所有していないことを示します。
auto_ptr
:用心深くてもトラップが多すぎるので非推奨ですので使用しないでください。unique_ptr
:単独所有権。shared_ptr
:共有所有権weak_ptr
:所有権がないため、裏で削除される可能性があります。- 生のポインタ
- 明示的に所有権なし、より長い寿命が保証される
- または手動による所有権管理。
だから私が探していることは、できれば弱いyousptrです。 shared_ptrに変換することはできません。
あなたはあなたの1つの小さなヘルパークラスを配らせることができます:
template<typename T>
class NonConvertibleWeakPtr
{
public:
NonConvertibleWeakPtr(const std::shared_ptr<T>& p) : p_(p) {}
... // other constructors / assignment operators
bool expired() const { return p_.expired(); }
T* operator->() const { return get(); }
T& operator*() const { return *get(); }
private:
T* get() const { return p_.lock().get(); }
private:
std::weak_ptr<T> p_;
};
.
ポインタがまだ有効かどうかを確認できるので、これはRAWポインタよりもわずかに優れています。
使用例:
std::shared_ptr<int> sp = std::make_shared<int>(5);
{
NonConvertibleWeakPtr<int> wp(sp);
if(!wp.expired()) {
std::cout << *wp << std::endl;
}
}
.
しかし、ユーザはそれを例えばstd::shared_ptr<T> blah(&(*wp));
で誤用することができるが、もう少し犯罪的なエネルギーが必要です。