シェアードポインタ

共有のオーナーシップ、自動的な無効化、弱い参照などをサポートするスマートポインタ

Windows
MacOS
Linux

シェアードポイント は強力な Nullable 型スマートポインタです。シェアードポインタは本質的に、スマートポインタの全ての基本的なメリットを持ち、メモリリーク、ダングリング ポインタ、初期化されていないメモリへのポインタをやメモリが初期化されないことなどを防ぎます。同時に以下のような機能もあります。

  • 共有のオーナーシップ 参照カウントによって、複数のシェアードポインタに対して参照されている間は参照しているデータ オブジェクトが絶対に削除されないようにできます。

  • 自動無効化 : Volatile オブジェクトをダングリング ポインタを心配せずに安全に参照できます。

  • 弱い参照カウント: Weak Pointers は参照サイクルを中断します。

  • 目的表示: オブザーバーとオーナーを区別し (共有の参照 ) non-nullable 型の参照を提供します。

シェアードポインタには注目すべき基本的な性質があります。

  • 非常に堅牢なシンタックス

  • 非侵入型 (しかしリフレクションは可能)

  • スレッドセーフ (条件付き)

  • 優れたパフォーマンス、メモリへの負担が軽減

シェアードポインタは 共有の参照 と似ています。大きな違いは、共有の参照が Nullable 型でないため常に参照が有効なオブジェクトである点です。共有の参照とシェアードポインタのどちらかを選ぶとしたら、空または Nullable 型オブジェクトが必要な場合を除いて共有の参照を選ぶとよいでしょう。

宣言と初期化

シェアードポインタは Nullable 型なので、データ オブジェクトの有無に関係なく初期化できます。以下は、新しいシェアードポインタを作成する例です。

// Create an empty shared pointer
TSharedPtr<FMyObjectType> EmptyPointer;
// Create a shared pointer to a new object
TSharedPtr<FMyObjectType> NewPointer(new FMyObjectType());
// Create a Shared Pointer from a Shared Reference
TSharedRef<FMyObjectType> NewReference(new FMyObjectType());
TSharedPtr<FMyObjectType> PointerFromReference = NewReference;
// Create a Thread-safe Shared Pointer
TSharedPtr<FMyObjectType, ESPMode::ThreadSafe> NewThreadsafePointer = MakeShared<FMyObjectType, ESPMode::ThreadSafe>(MyArgs);

2 つめのサンプルでは、そのオブジェクトを参照しているシェアード ポインタがないので、NodePtr は効率駅に新しい FMyObjectType オブジェクトを維持します。そのオブジェクトを指定するシェアード ポインタまたは共有の参照がなく、NodePtr は範囲外になると、オブジェクトは破壊されます。

シェアード ポインタをコピーすると、参照するオブジェクトへの参照が 1 つ追加されます。

// Increase the reference count of whatever object ExistingSharedPointer references.
TSharedPtr<FMyObjectType> AnotherPointer = ExistingSharedPointer;

参照するシェアード ポインタ (または共有の参照) がなくなるまで、オブジェクトは存在し続けます。

シェアード ポインタをリセットするには、Reset 関数を使用する、または以下のように null ポインタを割り当てます。

PointerOne.Reset();
PointerTwo = nullptr;
// PointerOne と PointerTwo は両方とも nullptr を参照するようになりました。

MoveTemp (または MoveTempIfPossible) 関数を使って、シェアード ポインタのコンテンツを別のシェアード ポインタへ転送することができます (移動元のシェアード ポインタは空になります)。

// Move the contents of PointerOne over to PointerTwo.PointerOne はこの後 nullptr を参照します。
PointerTwo = MoveTemp(PointerOne);
// Move the contents of PointerTwo over to PointerOne.PointerTwo はこの後 nullptr を参照します。
PointerOne = MoveTempIfPossible(PointerTwo);

MoveTempMoveTempIfPossible の違いは、MoveTemp には 非定数型左辺値 (lvalue) 上でのみ実行できる静的アセットが含まれていることです。

シェアード ポインタと共有の参照間の変換

シェアード ポインタと共有の参照間での変換は一般的です。共有の参照は暗示的にシェアード ポインタへ変換し、新しいシェアード ポインタは有効なオブジェクトを参照するという保証が追加されています。変換は通常の記法で処理されます。

TSharedPtr<FMyObjectType> MySharedPointer = MySharedReference;

シェアード ポインタが non-null オブジェクトを参照している限り、Shared Pointer 関数の ToSharedRef を使ってシェアード ポインタから共有の参照を作成できます。null のシェアード ポインタから共有の参照を作成しようとするとアサートに問題が発生します。

// Ensure your shared pointer is valid before dereferencing to avoid a potential assertion.
If (MySharedPointer.IsValid())
{
    MySharedReference = MySharedPointer.ToSharedRef();
}

比較

シェアードポインタ同士で等値をテストすることができます。ここでの等値の定義は、両方のシェアードポインタが同じオブジェクトを参照していることです。

TSharedPtr<FTreeNode> NodeA, NodeB;
if (NodeA == NodeB)
{
    // ...
}

IsValid 関数と bool 演算子はシェアードポインタが有効なオブジェクトを参照するかどうかを設定します。Get を呼び出して有効な (non-null) オブジェクト ポインタを返すかどうか確認することもできます。

if (Node.IsValid())
{
    // ...
}
if (Node)
{
    // ...
}
if (Node.Get() != nullptr)
{
    // ...
}

逆参照とアクセス

ポインタの逆参照、メソッドの呼出し、そしてメンバへのアクセスは、通常の C++ ポインタと同じ方法で設定します。また、逆参照を行う前に、IsValid`関数を呼び出す、またはオーバーロードされた bool` 演算子を使って、C++ ポインタに対して行うようにヌルチェックも実施すべきです。

// Check that Node references a valid object before dereferencing.
if (Node)
{
    // Any of the following three lines of code will dereference Node and call ListChildren on its object:
    Node->ListChildren();
    Node.Get()->ListChildren();
    (*Node).ListChildren();
}

カスタム デリータ

シェアード ポインタと共有の参照は、参照しているオブジェクトに対するカスタム デリータをサポートしています。カスタム削除コードを実行するには、スマート ポインタの作成時にパラメータとして実行するラムダ関数を以下のように指定します。

void DestroyMyObjectType(FMyObjectType* ObjectAboutToBeDeleted)
{
    // Custom deletion code goes here.
}
// These functions create Smart Pointers with custom deleters.
TSharedRef<FMyObjectType> NewReference(new FMyObjectType(), [](FMyObjectType* Obj){ DestroyMyObjectType(Obj); });
TSharedPtr<FMyObjectType> NewPointer(new FMyObjectType(), [](FMyObjectType* Obj){ DestroyMyObjectType(Obj); });
Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback