namespace std {
template <class T, class... Args>
shared_ptr<T> make_shared(Args&&... args); // (1)
template <class T>
shared_ptr<T> make_shared(size_t N); // (2) C++20 から
template <class T>
shared_ptr<T> make_shared(); // (3) C++20 から
template <class T>
shared_ptr<T> make_shared(size_t N, const remove_extent_t<T>& u); // (4) C++20 から
template <class T>
shared_ptr<T> make_shared(const remove_extent_t<T>& u); // (5) C++20 から
}
概要
shared_ptr
オブジェクトを構築する。
効果
型T
のオブジェクトにメモリを割り当てる(T
がU[]
の場合はU[N]
。N
はそれぞれのオーバーロードで指定された引数から決定される)。
オブジェクトは、それぞれのオーバーロードで指定された引数から初期化される。
例外がスローされた場合、関数は効果がない。
配列型U
のオブジェクトが(同じ型の)u
の初期値を持つように指定されている場合、これは、オブジェクトの各配列要素が初期値としてu
からの対応する要素を持つことを意味すると解釈される。
配列タイプのオブジェクトがデフォルトの初期値を持つように指定されている場合、これはオブジェクトの各配列要素がデフォルトの初期値を持つ(値初期化される)ことを意味すると解釈される。
非配列型U
の(サブ)オブジェクトが、v
またはU(l ...)
の初期値を持つように指定されている場合(l...
はコンストラクタ引数のリスト)、make_shared
は、式::new (pv) U(v)
または::new (pv) U(l...)
を使用して、この(サブ)オブジェクトを初期化する。ここで、pv
の型はvoid*
であり、型U
のオブジェクトを保持するのに適したストレージを指す。
非配列型U
の(サブ)オブジェクトがデフォルトの初期値を持つように指定されている場合、この関数は、式 ::new (pv) U()
を使用してこの(サブ)オブジェクトを初期化する。void*
は型U
のオブジェクトを保持するのに適したストレージを指す。
配列要素は、アドレスの昇順で初期化される。
戻り値によって管理されるオブジェクトのlifetime
が終了するか、配列要素の初期化が例外をスローすると、初期化された要素は元の構造の逆の順序で破棄される。
この関数によって初期化された非配列型U
の(サブ)オブジェクトを破棄する場合、式pv->~U()
によって破棄される。pvは型U
のオブジェクトを指す。
- (1) : 初期値
T(forward<Args>(args)...)
を持つ型T
のオブジェクトへのshared_ptr
を返す。Tが配列型でない場合にのみ、このオーバーロードはオーバーロード解決に関与する。この関数によって呼び出されるshared_ptr
コンストラクタは、型T
の新しく構築されたオブジェクトのアドレスでshared_from_this
を有効にする。 - (2) : デフォルトの初期値を持つ
U[N]
型のオブジェクトへのshared_ptr
を返す。ここで、U
はremove_extent_t<T>
である。T
の形式がU[]
の場合にのみ、このオーバーロードはオーバーロード解決に関与する。 - (3) : デフォルトの初期値を持つ
T
型のオブジェクトへのshared_ptr
を返す。このオーバーロードは、T
がU[N]
の形式の場合にのみオーバーロード解決に関与する。 - (4) :
U[N]
型のオブジェクトへのshared_ptr
を返す。ここで、U
はremove_extent_t<T>
であり、各配列要素の初期値はu
である。T
の形式がU[]
の場合にのみ、このオーバーロードはオーバーロード解決に関与する。 - (5) : 型
T
のオブジェクトへのshared_ptr
を返す。ここで、型remove_extent_t<T>
の各配列要素は初期値u
を持つ。
戻り値
型T
に対する shared_ptr<T>
オブジェクトを生成し返却する。
このとき、args...
で受け取った引数リストを型 T
のコンストラクタへ渡してshared_ptr<T>
型のオブジェクトを生成する。
事後条件
r.get() != 0 && r.use_count() == 1
, ここで、r
は戻り値である。
例外
bad_alloc
、またはallocate
またはオブジェクトの初期化からスローされた例外。
備考
shared_ptr<T>(new T(args...));
というように、コンストラクタを呼び出す方法でもshared_ptr
オブジェクトを構築できる。しかしこの方法では、以下の2つのメモリ確保が必要になり、効率がよくない:
- ユーザーによるオブジェクトの生成
- 内部的な参照カウンタの生成
make_shared()
は内部的にオブジェクトを生成するため、オブジェクトの生成と参照カウンタの生成を、1つの大きなブロックとしてメモリを確保するため、より効率的になる。
メモリの確保にユーザー定義のアロケータを使用したい場合には、 allocate_shared()
を使用する。
この関数では初期値が指定されない場合に確保した領域にオブジェクトが値初期化され構築される。値初期化においては、組み込み型は0
相当の値で初期化され、クラス型はデフォルトコンストラクタによって初期化される。この関数でメモリを確保した後ですぐに別の値で上書きしている場合、代わりにmake_shared_for_overwrite()
を使用することで初期化のオーバーヘッドを削減できる可能性がある。
例
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(42);
if(sp) {
std::cout << *sp << std::endl;
}
}
xxxxxxxxxx
#include <memory>
#include <iostream>
int main() {
std::shared_ptr<int> sp = std::make_shared<int>(42);
if(sp) {
std::cout << *sp << std::endl;
}
}
出力
42
バージョン
言語
- C++11
処理系
- Clang: 3.2 ✅, 3.3 ✅
- GCC: 4.4 ✅, 4.7.3 ✅, 4.8.2 ✅
- ICC: ??
- Visual C++: 2010 ✅, 2012 ✅, 2013 ✅
- 2010〜2012 でも使用可能だが、コンパイラが可変引数テンプレートに対応していないため、最大10個の引数を受け取れる形で実装されている。