メインコンテンツにスキップ
モジュール 7 · レッスン 2 / 2コース内の 16/18~12 min
モジュールのレッスン (2/2)

std::weak_ptr

std::shared_ptr は非常に便利ですが、共有所有権のみに依存すると、循環参照 (または循環依存関係) として知られる問題が発生する可能性があります。

2 つ以上のオブジェクトのそれぞれに、他方を指す shared_ptr が含まれている場合、閉じたループが作成されます。この状況では、どちらのオブジェクトの参照カウントもゼロにならないため、割り当て解除ができず、メモリ リークが発生します。

std::weak_ptr とは

所有権サイクルを断ち切るために、標準ライブラリは std::weak_ptr を提供します。これは、shared_ptr によって管理されるオブジェクトを監視するスマート ポインターですが、参照カウントは増加しません。

リソースを直接所有していないため、その破壊を防ぐことはできません。

C++
#include <memory>

std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Does not increment reference count!

リソースの確認とアクセス

weak_ptr はリソースを所有していないため、リソースはいつでも割り当て解除される可能性があります (関連するすべての shared_ptr インスタンスがスコープ外になった場合)。

監視されたリソースを使用するには、次のことを行う必要があります。

  1. expired() を使用して、それがまだ有効かどうかを確認します。
  2. lock() メソッドを使用して、weak_ptr を shared_ptr に一時的に変換します。リソースがまだアクティブな場合、lock() は有効な shared_ptr を返します。それ以外の場合は、NULL ポインター (nullptr) を返します。
C++
if (!weak.expired()) {
    // lock() creates a temporary shared_ptr to ensure safe access
    if (std::shared_ptr<int> sharedAccess = weak.lock()) {
        std::cout << *sharedAccess << std::endl;
    }
} else {
    std::cout << "Resource deallocated!" << std::endl;
}

自分で試してみてください

運動#cpp.m7.l2.e1
試行回数: 0読み込み中…

sPtr から初期化された wPtr という名前の std::weak_ptr<int> を宣言します。次に、std::cout を使用して、wPtr.expired() によって返されたブール値の結果を出力します。

エディターを読み込み中…
ヒントを表示

同じジェネリック型 `<int>` を示す `weak_ptr` を宣言し、それに `sPtr` を直接割り当てます。

3 回の試行後に解決策が利用可能になります

運動#cpp.m7.l2.e2
試行回数: 0読み込み中…

wPtr で lock() メソッドを使用して、一時的なshared_ptrを取得します。操作が成功した場合 (ポインターが null でない場合)、逆参照された値を出力します。

エディターを読み込み中…
ヒントを表示

「wPtr.lock()」を呼び出して「if」ブロック内の変数を初期化し、それをアスタリスク「*」で逆参照してリソースを出力します。

3 回の試行後に解決策が利用可能になります