名前空間
変種
操作

std::make_shared, std::make_shared_for_overwrite

提供: cppreference.com
< cpp‎ | memory‎ | shared ptr
 
 
ユーティリティライブラリ
汎用ユーティリティ
日付と時間
関数オブジェクト
書式化ライブラリ (C++20)
(C++11)
関係演算子 (C++20で非推奨)
整数比較関数
(C++20)
スワップと型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
一般的な語彙の型
(C++11)
(C++17)
(C++17)
(C++17)
(C++17)

初等文字列変換
(C++17)
(C++17)
 
動的メモリ管理
スマートポインタ
(C++11)
(C++11)
(C++11)
(C++17未満)
(C++11)
アロケータ
メモリリソース
未初期化記憶域
ガベージコレクションサポート
その他
(C++20)
(C++11)
(C++11)
C のライブラリ
低水準のメモリ管理
 
 
ヘッダ <memory> で定義
template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );
(1) (C++11以上)
(T が配列でない場合)
template<class T>
shared_ptr<T> make_shared( std::size_t N );
(2) (C++20以上)
(T が U[] の場合)
template<class T>
shared_ptr<T> make_shared();
(3) (C++20以上)
(T が U[N] の場合)
template<class T>
shared_ptr<T> make_shared( std::size_t N, const std::remove_extent_t<T>& u );
(4) (C++20以上)
(T が U[] の場合)
template<class T>
shared_ptr<T> make_shared( const std::remove_extent_t<T>& u );
(5) (C++20以上)
(T が U[N] の場合)
template<class T>
shared_ptr<T> make_shared_for_overwrite();
(6) (C++20以上)
(T が U[] でない場合)
template<class T>
shared_ptr<T> make_shared_for_overwrite( std::size_t N );
(7) (C++20以上)
(T が U[] の場合)
1) argsT のコンストラクタに対する引数リストとして使用して T 型のオブジェクトを構築し、それを std::shared_ptr にラップします。 オブジェクトは式 ::new (pv) T(std::forward<Args>(args)...) を用いたかのように構築されます。 ただし pvT 型のオブジェクトを保持するのに適した記憶域を指す内部的な void* ポインタです。 記憶域は、一般的には、 shared_ptr の制御ブロックと T オブジェクトの両方に対して1回で確保を行うため、 sizeof(T) より大きくなります。 この関数によって呼ばれる std::shared_ptr のコンストラクタは、 T 型の新たに構築されたオブジェクトを指すポインタで shared_from_this を有効化します。 このオーバーロードは、T が配列型でない場合にのみ、オーバーロード解決に参加します。
2,3) (1) と同じですが、構築されるオブジェクトは配列 (多次元かもしれない) であり、その std::remove_all_extents_t<T> 型の非配列要素は配置 new 式 ::new(pv) std::remove_all_extents_t<T>() によって行われたかのように値初期化されます。 オーバーロード (2) は、最初の次元のサイズが N の配列を作成します。 配列要素はそのアドレスの昇順に初期化され、生存期間を終えるときはその逆の順序で破棄されます。
4,5) (2,3) と同じですが、すべての要素はデフォルト値 u から初期化されます。 U が配列型でなければ、これは (1) の場合と同じ配置 new 式で行われたかのように行われます。 そうでなければ、これは配列 (多次元かもしれない) のすべての非配列要素が u 内の対応する要素で (1) の場合と同じ配置 new 式で初期化されたかのように行われます。 オーバーロード (4) は、最初の次元のサイズが N の配列を作成します。 配列要素はそのアドレスの昇順に初期化され、生存期間を終えるときはその逆順で破棄されます。
6) (1) と同じですが、 T が配列型でない場合および TU[N] の場合は、作成されるオブジェクトはデフォルト初期化されます。
7) (2) と同じですが、個々の配列要素はデフォルト初期化されます。

いずれの場合においても、オブジェクト (または T が配列型の場合は個々の要素) (C++20以上)p->~X() によって破棄されます。 ただし p はオブジェクトを指すポインタで X はその型です。

目次

[編集] 引数

args - T のインスタンスを構築するための引数リスト
N - 使用する配列サイズ
u - 配列のすべての要素を初期化するための初期値

[編集] 戻り値

T 型のインスタンスの std::shared_ptr

[編集] 例外

std::bad_alloc または T のコンストラクタによって投げられるあらゆる例外。 例外が投げられた場合、この関数は効果を持ちません。 配列の構築中に例外が投げられた場合、すでに初期化された要素は逆順で破棄されます。 (C++20以上)

[編集] ノート

この関数は std::shared_ptr<T>(new T(args...)) の代替として使用することができます。 トレードオフは以下の通りです。

  • std::shared_ptr<T>(new T(args...)) は少なくとも2回の確保を行います (1回は T のオブジェクトのためで、1回は shared_ptr の制御ブロックのためです)。 std::make_shared<T> は一般的に1回しか確保を行いません。 (標準はそのように推奨していますが、要求はしていません。 すべての既知の実装はそれを行っています。)
  • すべての shared_ptr の生存期間が終わった後も、 std::weak_ptrstd::make_shared によって作成された制御ブロックを参照している場合、 T によって占められていたメモリは、すべての weak_ptr も同様に破棄されるまで、残り続けます。 sizeof(T) が大きい場合、これは望ましくないかもしれません。
  • std::shared_ptr<T>(new T(args...)) は、それが可能な場所で実行された場合、 T のパブリックでないコンストラクタを呼ぶことができます。 std::make_shared は、選択されたコンストラクタへのパブリックなアクセスを要求します。
  • std::shared_ptr のコンストラクタと異なり、 std::make_shared ではカスタムアロケータを使用できません。
  • std::make_shared::new を使用します。 そのため、クラス特有の operator new を使用して何らかの特殊な動作を行っている場合、 std::shared_ptr<T>(new T(args...)) とは異なる動作になります。
  • std::shared_ptr は (C++17 以降) 配列型をサポートしますが、 std::make_shared はしません。 この機能は boost::make_shared ではサポートされています。
(C++20未満)
  • f(std::shared_ptr<int>(new int(42)), g()) のようなコードは、 gnew int(42) の後に呼ばれて例外を投げた場合、メモリリークを発生し得ます。 f(std::make_shared<int>(42), g()) は、2つの関数呼び出しがインターリーブしないため、安全です。
(C++17未満)

コンストラクタが U* 型のポインタ ptrshared_from_this を有効化するとは、 U曖昧でなくアクセス可能な (C++17以上) std::enable_shared_from_this の特殊化を基底クラスに持つかどうか調べ、もし持つのであれば以下の文を評価する、という意味です。

if (ptr != nullptr && ptr->weak_this.expired())
  ptr->weak_this = std::shared_ptr<std::remove_cv_t<U>>(*this,
                                  const_cast<std::remove_cv_t<U>*>(ptr));

ただし weak_thisstd::shared_from_this が持つ std::weak_ptr 型の隠された mutable なメンバです。 weak_this メンバの代入はアトミックでなく、同じオブジェクトに対するあらゆる潜在的な並行アクセスと衝突します。 これにより shared_from_this() の将来の呼び出しが、この生のポインタのコンストラクタによって作成された shared_ptr と、所有権を共有することが保証されます。

上記の説明用コード内の判定 ptr->weak_this.expired() は、すでに所有者がある場合に weak_this が再代入されないようにします。 C++17 以降この判定が要求されます。

[編集]

#include <iostream>
#include <memory>
#include <type_traits>
 
struct C
{
  C(int i) : i(i) {} // (C++20 未満では) コンストラクタが必要
  int i;
};
 
int main()
{
    auto sp = std::make_shared<C>(12);
 
    static_assert(std::is_same_v<decltype(sp), std::shared_ptr<C>>);
 
    std::cout << sp->i << '\n';
}

出力:

12

[編集] 関連項目

新しい shared_ptr を構築します
(パブリックメンバ関数) [edit]
アロケータを使用して確保した新しいオブジェクトを管理する shared_ptr を作成します
(関数テンプレート) [edit]
新しいオブジェクトを管理する unique_ptr を作成します
(関数テンプレート) [edit]
確保関数
(関数) [edit]