namespace std {
template <class T, class... Args>
shared_ptr<T>
make_shared(Args&&... args); // (1) C++11
template <class T, class... Args>
constexpr shared_ptr<T>
make_shared(Args&&... args); // (1) C++26
template <class T>
shared_ptr<T>
make_shared(size_t N); // (2) C++20
template <class T>
constexpr shared_ptr<T>
make_shared(size_t N); // (2) C++26
template <class T>
shared_ptr<T>
make_shared(); // (3) C++20
template <class T>
constexpr shared_ptr<T>
make_shared(); // (3) C++26
template <class T>
shared_ptr<T>
make_shared(size_t N,
const remove_extent_t<T>& u); // (4) C++20
template <class T>
constexpr shared_ptr<T>
make_shared(size_t N,
const remove_extent_t<T>& u); // (4) C++26
template <class T>
shared_ptr<T>
make_shared(const remove_extent_t<T>& u); // (5) C++20
template <class T>
constexpr shared_ptr<T>
make_shared(const remove_extent_t<T>& u); // (5) C++26
}
概要
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;
}
}
出力
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個の引数を受け取れる形で実装されている。