ちょうど見たときにRAIIのためにウィキペディアを読んSingle
でShared
所有していました。
それをグーグルで検索しましたが、有用な答えが見つかりませんでした!
この概念を男子生徒に説明できる人はいますか?
それは本質的にunique_ptr
対shared_ptr
です。
単一の所有権 (一意の所有権とも呼ばれます) は、リソースが単一のクラス インスタンスによって所有されていることを意味します。そのインスタンスが存在しなくなると、リソースは (デストラクタを介して) 解放されます。見つけた RAII クラスの大半は、std::vector
.
共有所有権とは、リソースが複数のクラス インスタンス間で共有されることを意味します。リソースは、すべてのインスタンスが存在しなくなった場合にのみ解放されるため、何らかの形式の参照カウントまたはガベージ コレクションが必要になります。共有所有権が必要な場所の例は、コピーするのに非常にコストがかかる不変リソースへのハンドルです。グラフでも使用されているのを見たことがあります。
ポインターの観点から考えると役立つ場合があります。単一の所有権には所有ポインタが 1 つしかなく、共有には複数の所有ポインタがあります。もちろん、RAII にはポインターが含まれない場合もあります。
+---------------+
|Shared instance|
+--------+ +------------+--+ +---------------+
|Resource| | +----------+Shared instance|
+--------+ v v +---------------+
^ +--------+
| |Resource|<-----------+
| +--------+ +---+-----------+
| ^ |Shared instance|
+------+--------+ | +---------------+
|Unique Instance| |
+---------------+ |
+------+--------+
|Shared instance|
+---------------+
所有権は、可変ライフタイムの概念と強く結びついています。
質問に答えることができる場合、このメモリのチャンクがなくなるのはいつですか? 、所有権の問題に答えることができます。
そのメモリのチャンクが 1 つの変数の有効期間のみに関連付けられている場合、所有権は 1 つになります。
ヒープまたは動的割り当てとスタックまたは自動変数について考えることも重要であることに注意してください。自動変数を使用すると、それらが範囲外になると、それらに関連付けられたメモリが取得されます。動的割り当てでは、一般的なケースでは同じではありません。単一の所有権にstd::unique_ptr<>などの新しい機能を使用すると、動的メモリのチャンクがスコープ外になったときにそれ自体をクリーンアップすることができます。そのメモリのチャンクへの参照が多数あり、参照がいつなくなるかの順序が不明な場合は、複数の所有権のためにstd::shared_ptr<>のようなものが必要になる場合があります。
所有権は、誰がリソースを解放する責任があるかということになります。通常、コードの一部 (関数であれクラスであれ) がリソースの唯一の所有者であると言えます。リソースの処理が完了したら、所有者はリソースがリークしないようにリソースを解放する必要があります。これは、単一または一意の所有権として知られています。
同様に、コードの 2 つ以上の個別の部分がクラスまたは関数である可能性があり、両方が同じリソースをカウントする、共有所有権の概念が存在します。この場合、リソースを解放する前に、両方がリソースを必要としなくなっている必要があります。
C++ は、所有権のセマンティクスを伝達および強制するための 2 つの便利なラッパーを提供します。所有権のセマンティクスは、上記で説明したものです。これらのラッパーは、RAIIの概念を一般化したものです。つまり、リソースがスコープから外れると、そのリソースは自動的に解放されます。
unique_ptr
-- 一意のポインタでラップされたオブジェクトは、スコープ外になるとすぐに解放されます。つまり、関数が戻るか、クラスが破棄されます。
shared_ptr
-- 共有ポインタにラップされたオブジェクトは、すべての「強い参照」が範囲外になるまで利用可能です。これは、参照カウントと呼ばれる概念です。最後の参照が範囲外になると、リソースは解放されます。
所有権のセマンティクスは、C++ などの言語では非常に重要であるため、最新のC++ がそれをどのように伝え、強制するかを理解することをお勧めします。unique_ptr
との正しい使い方を学ぶことから始めることができますshared_ptr
。
スマート ポインター / raii に関連して、共有所有権とは、複数のオブジェクトが同じリソースを参照できる場合であり、このリソースは、リソースを参照するそのオブジェクトのすべてのインスタンスが分解された場合にのみ解放されます。
// shared ownership
{
std::shared_ptr<SomeClass> i(new SomeClass());
{
std::shared_ptr<SomeClass> j = i;
{
std::shared_ptr<SomeClass> k = j;
// at this point i, j, k all own the same object
}
// k deconstructed and no longer shares ownership of the resource
}
// j deconstructed and no longer shares ownership of the resource
}
// i deconstructed and he resource is also released / free'd
共有 (一意) の所有権では、オブジェクトと共に消滅するか、他のオブジェクトに渡されます
// single/unique ownership
{
std::unique_ptr<SomeClass> i(new SomeClass());
{
std::unique_ptr<SomeClass> j = std::move(i); // k takes ownership of the object from i
}
// j is deconstructed and the resource is also released / free'd
}
// i deconstructed and nothing is released, as the ownership already passed to j
単一の所有権とは、所有者がリソースを使い終わったら、それを削除する必要があることを意味します。
所有権が共有されている場合は、他の所有者がまだ使用している可能性があるため、削除できません。したがって、リソースの削除は、通常は参照カウントによる何らかの手段で調整する必要があります。