弱いポインタ はオブジェクトに対する弱い参照を格納します。弱いポインタは シェアード ポインタ や 共有の参照 とは異なり、参照するオブジェクトの破棄を防止しません。
弱いポインタが参照するオブジェクトにアクセスする前に、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
が返すシェアード ポインタは、コードでクリアされるか、スコープ外になるまでオブジェクトを存続させるためです。