shared_ptrとweak_ptrによる共有所有
参照カウントで所有権を共有し、weak_ptrで循環参照を断ち切ります。
「shared_ptrとweak_ptrによる共有所有」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
オブジェクトの共有
プログラムの複数の部分で、1つのオブジェクトを存続させる必要がある場合があります。std::shared_ptr<T>は、参照カウントによる共有所有権を管理します。
shared_ptrの作成
std::make_sharedを使います。制御ブロックとオブジェクトを1回のメモリ確保で確保できます。
#include <memory>
auto s = std::make_shared<Widget>(42);
std::cout << s.use_count(); // 1コピーすると所有権を共有する
shared_ptrをコピーすると、参照カウントが増加します。破棄または再代入すると減少します。カウントが0になると、オブジェクトが削除されます。
auto a = std::make_shared<Widget>();
auto b = a; // ref count is now 2
std::cout << a.use_count(); // 2内部の仕組み
shared_ptrは2つのポインターを保持します。1つはオブジェクトを指し、もう1つは参照カウントを含む制御ブロックを指します。制御ブロックはヒープ上に確保されます。
アトミックな参照カウント
参照カウントにはアトミック操作が使われるため、shared_ptrをスレッド間で安全にコピーできます。ただし、指し示されるオブジェクト自体が自動的にスレッドセーフになるわけではありません。
リセットと再代入
新しい値を代入すると、古い参照カウントが減少し、新しい参照カウントが増加します。reset()を使うと、shared_ptrは空になります。
生ポインターからの shared_ptr(避ける)
同じ生ポインターから2つの shared_ptrを構築してはいけません。それぞれが独自の制御ブロックを持つことになるためです。常に make_sharedを使用してください。
// BUG
Widget* raw = new Widget();
std::shared_ptr<Widget> a(raw);
std::shared_ptr<Widget> b(raw); // disaster: two control blocks循環参照の問題
互いを参照する2つの shared_ptrは循環を形成します。どちらも参照カウントが0にならないため、どちらも解放されません。メモリリークが発生します。
struct Node {
std::shared_ptr<Node> next;
};
auto a = std::make_shared<Node>();
auto b = std::make_shared<Node>();
a->next = b;
b->next = a; // cycle — never freedweak_ptrで循環を断つ
std::weak_ptr<T>は、参照カウントに参加せずに shared_ptrを監視します。関係の一方をweakにして、循環を断ってください。
struct Node {
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev; // weak — does not own
};weak_ptrの使用
weak_ptrを直接デリファレンスすることはできません。lock()を呼び出して shared_ptrを取得してください(オブジェクトが破棄済みの場合は空になります)。
std::weak_ptr<Widget> w = sharedPtr;
if (auto p = w.lock()) {
p->use(); // safe — we have a shared_ptr now
} else {
std::cout << "object expired";
}unique_ptrとのコスト比較
shared_ptrはより大きく(2つのポインターと制御ブロック)、より低速です(参照カウントがアトミックであるため)。所有権を本当に共有する必要がある場合にのみ使用してください。
確認問題
std::weak_ptrの典型的な用途は何ですか?
まとめ
shared_ptrはアトミックな参照カウントで所有権を追跡します。make_sharedを使用し、循環参照に注意して、weak_ptrで循環を断ってください。共有が不要な場合は unique_ptrを優先してください。
よくある質問
「shared_ptrとweak_ptrによる共有所有」レッスンは無料ですか?
はい。「shared_ptrとweak_ptrによる共有所有」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「shared_ptrとweak_ptrによる共有所有」で何を学びますか?
参照カウントで所有権を共有し、weak_ptrで循環参照を断ち切ります。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。
「shared_ptrとweak_ptrによる共有所有」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- スマートポインターが生のnewとdeleteを置き換える理由
- unique_ptrによる単独所有
- shared_ptrとweak_ptrによる共有所有
- カスタムデリーターとmake関数