Weak Pointers

弱い参照を格納してオブジェクトの破棄を防止しないスマート ポインタについて説明します。

Choose your operating system:

Windows

macOS

Linux

弱いポインタ はオブジェクトに対する弱い参照を格納します。弱いポインタは シェアード ポインタ 共有の参照 とは異なり、参照するオブジェクトの破棄を防止しません。

弱いポインタが参照するオブジェクトにアクセスする前に、 Pin 関数を使用してシェアード ポインタを作成する必要があります。これにより、使用されているオブジェクトが削除されず存続することが保証されます。弱いポインタがオブジェクトを参照しているかどうかをのみを確定する必要がある場合は、弱いポインタを`nullptr と比較するか、弱いポインタに対して`IsValid を呼び出すことができます。

弱いポインタの使用は、目的を示すうえで役立ちます。つまり、弱いポインタは、参照されているオブジェクトをそのオブジェクトを所有することなく監視して、その存続期間を制御しないことを示します。

宣言、初期化、および代入

空の弱いポインタを作成したり、共有の参照、シェアード ポインタ、または別の弱いポインタから弱いポインタを作成することができます。

// Allocate a new data object and create a strong reference to it.
TSharedRef<FMyObjectType> ObjectOwner = MakeShared<FMyObjectType>();
// Create a weak pointer to the new data object.
TWeakPtr<FMyObjectType> ObjectObserver(ObjectOwner);

弱いポインタはオブジェクトの破棄を防止しません。たとえば、 ObjectOwner をリセットすると、 ObjectObserver が依然としてスコープ内であるかどうかにかかわらずオブジェクトは破棄されます。

// Assuming ObjectOwner was the only owner of its object, that object will be destroyed when ObjectOwner stops referencing it.
ObjectOwner.Reset();
// The Shared Pointer that Pin() generates will be null due to ObjectOwner referencing a null object.When treated as a bool, empty Shared Pointers evaluate to false.
if (ObjectObserver.Pin())
{
    // This code will run only if ObjectOwner was not the sole owner of our object.
    check(false);
}

弱いポインタは、有効なオブジェクトを参照しているかどうかにかかわらず、シェアード ポインタ同様、安全にコピーすることができます。

TWeakPtr<FMyObjectType> AnotherObjectObserver = ObjectObserver;

弱いポインタは使用し終えたらリセットできます。

// You can reset a Weak Pointer by setting it to nullptr.
ObjectObserver = nullptr;
// You can also use the Reset function.
AnotherObjectObserver.Reset();

シェアード ポインタへの変換

Pin 関数は弱いポインタのオブジェクトへのシェアード ポインタを作成します。シェアード ポインタがスコープ内にあり、オブジェクトを参照している間、そのオブジェクトは有効です。また、シェアード ポインタ ( Pin 関数が返すシェアード ポインタを含む) は、 true が有効なオブジェクトであれば、条件式内で bool 型と評価される場合があります。以下のコード パターンは、弱いポインタが有効なオブジェクトを参照しているかどうかを確認して、参照していれば少なくとも ( Pin 関数によって生成される) シェアード ポインタがスコープ外になるか明示的にクリアされるまで有効であり続けることを保証します。

// Acquire a Shared Pointer from the Weak Pointer and check that it references a valid object.
if (TSharedPtr<FMyObjectType> LockedObserver = ObjectObserver.Pin())
{
    // The Shared Pointer is valid only within this scope.
    // The object has been verified to exist, and the Shared Pointer prevents its deletion.
    LockedObserver->SomeFunction();
}

逆参照とアクセス

弱いポインタのオブジェクトにアクセスするには、まずその弱いポインタを Pin 関数でシェアード ポインタに昇格させます。これにより、シェアード ポインタまたは弱いポインタ上で Get 関数を経由して該当オブジェクトにアクセスできるようになります。この方法では、オブジェクトは使用中有効であり続けることが保証されます。

参照サイクルの中断

2 つ以上のオブジェクトがスマート ポインタを使用して相互に強い参照であり続ける場合は常に参照サイクルが存在します。このような場合、オブジェクトは常に他方のオブジェクトから参照されており、相互に削除を防止するため、一方が存在する限りどちらも削除できません。参照サイクルのどちらのオブジェクトにも外部からの参照がなければ、実質にリークします。弱いポインタは、参照するオブジェクトを保護しないため、このような参照サイクルを中断することができます。弱いポインタは、所有権を要求することなくオブジェクトを参照して、存続期間を延長できる可能性がある場合に使用します。

使用上の注意

弱いポインタはデータ オブジェクトの継続的な存在を保証する必要がない場合に役立ちますが、まさにこの特性が危険になる場合があります。弱いポインタの使用時に、次のような状態は注意が必要です。

  • Sets または Maps でのキーの使用。弱いポインタはいつでも無効になる可能性がありますが、コンテナに通知しないため、シェアード ポインタまたは共有の参照はキーとして動作するのに適しています。弱いポインタは値として使用することが安全です。

  • 弱いポインタは IsValid 関数を提供しますが、 IsValid を確認してもオブジェクトが一定期間有効であり続けることは保証されません。これは特にスレッド セーフなシェアード ポインタに当てはまります。別のスレッドの動作によっていつでも無効になる可能性があるからです。 Pin 関数は格納したオブジェクトへの逆参照またはアクセスにつながる確認のために推奨される手段です。これは、 Pin が返すシェアード ポインタは、コードでクリアされるか、スコープ外になるまでオブジェクトを存続させるためです。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル