0Pricing
C++ Academy · レッスン

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 freed

weak_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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. スマートポインターが生のnewとdeleteを置き換える理由
  2. unique_ptrによる単独所有
  3. shared_ptrとweak_ptrによる共有所有
  4. カスタムデリーターとmake関数
← C++ Academyに戻る