最終更新日時(UTC):
が更新

履歴 編集

function
<memory>

std::shared_ptr::コンストラクタ(C++11)

constexpr shared_ptr() noexcept;                         // (1)

template <class Y>
explicit shared_ptr(Y* p);                               // (2)

template <class Y, class Deleter>
shared_ptr(Y* p, Deleter d);                             // (3)

template <class Y, class Deleter, class Alloc>
shared_ptr(Y* p, Deleter d, Alloc a);                    // (4)

template <class Deleter>
shared_ptr(nullptr_t p, Deleter d);                      // (5)

template <class Deleter, class Alloc>
shared_ptr(nullptr_t p, Deleter d, Alloc a);             // (6)

template<class Y>
shared_ptr(const shared_ptr<Y>& r, T* p) noexcept;            // (7) C++11

template<class Y>
shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept; // (7) C++17

shared_ptr(const shared_ptr& r) noexcept;                // (8)

template <class Y>
shared_ptr(const shared_ptr<Y>& r) noexcept;             // (9)

shared_ptr(shared_ptr&& r) noexcept;                     // (10)

template <class Y>
shared_ptr(shared_ptr<Y>&& r) noexcept;                  // (11)

template <class Y>
explicit shared_ptr(const weak_ptr<Y>& r);               // (12)

template <class Y>
shared_ptr(auto_ptr<Y>&& r);                             // (13)
                                                         // C++11から非推奨
                                                         // C++17で削除

template <class Y, class Deleter>
shared_ptr(unique_ptr<Y, Deleter>&& r);                  // (14)

constexpr shared_ptr(nullptr_t);                         // (15)

template <class Y>
shared_ptr(shared_ptr<Y>&& r, element_type* p) noexcept; // (16) C++20

shared_ptrオブジェクトの構築

  • (1) : 所有権を持たない、空のshared_ptrオブジェクトを構築する。
  • (2) : 生ポインタの所有権を受け取る。
  • (3) : 生ポインタの所有権と、リソースを破棄する際に使用する関数オブジェクトを受け取る。
  • (4) : 生ポインタの所有権、リソースを破棄する際に使用する関数オブジェクト、アロケータを受け取る。
  • (5) : リソースを破棄する際に使用する関数オブジェクトを受け取り、ヌルポインタを所有するshared_ptrオブジェクトを構築する。
  • (6) : リソースを破棄する際に使用する関数オブジェクトと、アロケータを受け取り、ヌルポインタを所有するshared_ptrオブジェクトを構築する。
  • (7) : Yのメンバへのポインタを共有する。
  • (8), (9) : 他のshared_ptrオブジェクトと、リソースを共有する。
  • (10), (11) : 他のshared_ptrオブジェクトから、リソースの所有権を移動する。
  • (12) : weak_ptrオブジェクトが参照するリソースから、所有権を共有するshared_ptrオブジェクトを構築する。
  • (13) : auto_ptrオブジェクトから、リソースの所有権を移動する。
  • (14) : unique_ptrオブジェクトから、リソースの所有権を移動する。
  • (15) : (1)と同じく、所有権を持たない、空のshared_ptrオブジェクトを構築する。
  • (16) : (7)の右辺値版。Y*thisにムーブしつつ、それのメンバへのポインタを共有する。

要件

  • (2) C++11 :
    • pT*に変換可能であること。
    • Yが完全型であること。
    • delete pが妥当であること。
  • (2) C++17 :
    • pT*と互換があること。
    • Yが完全型であること。
    • Tが非配列である場合、式delete pが妥当であること。
    • Tが配列である場合、式delete[] pが妥当であること。
    • TU[N]形式である場合、関数ポインタ配列Y(*)[N]T*に変換可能である。
    • TU[]形式である場合、関数ポインタ配列Y(*)[]T*に変換可能である。
  • (3), (4), (5), (6) : pT*に変換可能であること。Deleterがコピー構築可能な型であり、そのコピーコンストラクタとデストラクタが例外を投げないこと。d(p)という式が妥当であること。
    • C++17 : 型Tが配列である場合、式delete[] pが妥当であること。型TU[N]形式である場合、関数ポインタ配列Y(*)[N]T*に変換可能である。
  • (9) C++11 : Y*T*に暗黙変換可能でない場合、この関数はオーバーロード解決から除外される。
  • (9) C++17 : Y*T*と互換でない場合、この関数はオーバーロード解決から除外される。
  • (11) : Y*T*に暗黙変換可能でない場合、この関数はオーバーロード解決から除外される。
  • (12) C++11 : Y*T*に変換可能であること。
  • (12) C++17 : Y*T*と互換であること。
  • (13) : r.release()によって返されるポインタ値が、T*に変換可能であること。Yが完全型であり、式delete r.release()が妥当であること。
  • (14) C++11 : unique_ptr<Y, Deleter>::pointerT*に変換可能でない場合、この関数はオーバーロード解決から除外される。
  • (14) C++17 : Y*T*と互換でなく、unique_ptr<Y, Deleter>::pointerelement_type*に変換可能でない場合、この関数はオーバーロード解決から除外される。

効果

  • (1) : 空のshared_ptrオブジェクトを構築する。
  • (2) C++11 : ポインタpを所有するshared_ptrオブジェクトを構築する。
  • (2) C++17 : 型Tが配列ではない場合、ポインタpを所有するshared_ptrオブジェクトを構築する。そうではない場合、ポインタpと、delete[] pを実行するデリータを所有するshared_ptrオブジェクトを構築する。
  • (3) : リソースを破棄する際に使用する関数オブジェクトdを受け取り、ポインタpを所有するshared_ptrオブジェクトを構築する。
  • (4) : リソースを破棄する際に使用する関数オブジェクトdを受け取り、ポインタpを所有するshared_ptrオブジェクトを構築する。アロケータオブジェクトaのコピーを、内部のメモリ確保に使用する。
  • (5) : リソースを破棄する際に使用する関数オブジェクトdを受け取り、ヌルポインタを所有するshared_ptrオブジェクトを構築する。
  • (6) : リソースを破棄する際に使用する関数オブジェクトdを受け取り、ヌルポインタを所有するshared_ptrオブジェクトを構築する。アロケータオブジェクトaのコピーを、内部のメモリ確保に使用する。
  • (7) : rの所有権を持ち、ポインタとしてはpを保持するshared_ptrオブジェクトを構築する。
  • (8), (9) : rが空の場合、空のshared_ptrオブジェクトを構築する。そうでなければ、rとリソースを共有するshared_ptrオブジェクトを構築する。
  • (10), (11) : rが持つ所有権を、*thisに移動する。
  • (12) : rが持つポインタのコピーを共有するshared_ptrオブジェクトを構築する。
  • (13) : rが持つ所有権を、*thisに移動する。
  • (14) : 以下のように、(3)のコンストラクタに委譲する。Deleterが参照型でなければshared_ptr(r.release(), r.get_deleter())を呼び出し、そうでなければshared_ptr(r.release(), ref(r.get_deleter()))
  • (15) : 空のshared_ptrオブジェクトを構築する。

事後条件

例外

  • (3), (4), (5), (6) : メモリ確保に失敗した場合、bad_alloc例外を送出する。例外送出時にはd(p)を呼び出すことが保証される。
  • (12) : r.expired() == trueの場合、bad_weak_ptr例外を送出する。
  • (13) : メモリ確保に失敗した場合、bad_allocもしくはその他実装定義の例外を送出する。

備考

アロケータは、参照カウンタのメモリ確保に使用される。

#include <cassert>
#include <memory>

struct X {
  int i;

  X(int i = 0)
    : i(i) {}
};

int main()
{
  // (1)
  // デフォルト構築。
  // 空のshared_ptrオブジェクトを構築する
  std::shared_ptr<int> p1;
  assert(p1.get() == nullptr);
  assert(p1.use_count() == 0);

  // (2)
  // ポインタの所有権を受け取る。
  std::shared_ptr<int> p2(new int(3));
  assert(*p2.get() == 3);
  assert(p2.use_count() == 1);

  // (3)
  // ポインタの所有権と、デリータを受け取る。
  // リソース解放時に、delete pの代わりにデリータが呼ばれる。
  std::shared_ptr<int> p3(new int(3), std::default_delete<int>());
  assert(*p3.get() == 3);
  assert(p3.use_count() == 1);

  // (4)
  // ポインタの所有権、デリータ、アロケータを受け取る。
  // アロケータは内部的にrebindされるので、要素型はなんでもいい。
  std::shared_ptr<int> p4(new int(3),
                          std::default_delete<int>(),
                          std::allocator<void>());
  assert(*p4.get() == 3);
  assert(p4.use_count() == 1);

  // (5)
  // デリータを受け取り、
  // ヌルポインタを所有するshared_ptrオブジェクトを構築する。
  std::shared_ptr<int> p5(nullptr, std::default_delete<int>());
  assert(p5.get() == nullptr);
  assert(p5.use_count() == 1);

  // (6)
  // デリータとアロケータを受け取り、
  // ヌルポインタを所有するshared_ptrオブジェクトを構築する。
  std::shared_ptr<int> p6(nullptr,
                          std::default_delete<int>(),
                          std::allocator<void>());
  assert(p6.get() == nullptr);
  assert(p6.use_count() == 1);

  // (7)
  // 要素型のメンバへのポインタを共有する。
  std::shared_ptr<X> p7_org(new X(3));
  std::shared_ptr<int> p7(p7_org, &(p7_org->i));
  assert(*p7.get() == 3); // p7はiへのポインタを所有する
  assert(p7.use_count() == p7_org.use_count()); // 所有権はコピー元のshared_ptrと共有する

  // (8)
  // 他のshared_ptrとリソースを共有する
  std::shared_ptr<int> p8_org(new int(3));
  std::shared_ptr<int> p8 = p8_org;
  assert(p8.get() == p8_org.get()); // p8_orgとo8はリソースを共有する
  assert(p8.use_count() == 2); // 所有者は2人

  // (10)
  // 他のshared_ptrからリソースを移動する
  std::shared_ptr<int> p10_org(new int(3));
  std::shared_ptr<int> p10 = std::move(p10_org);
  assert(*p10.get() == 3);
  assert(p10.use_count() == 1);
  assert(p10_org.use_count() == 0);

  // (12)
  // weak_ptrから構築
  std::shared_ptr<int> p12_org(new int(3));
  std::weak_ptr<int> w12(p12_org);
  if (std::shared_ptr<int> p12 = w12.lock()) {
    assert(*p12.get() == 3);
    assert(p12.use_count() == 2);
  }
  else {
    assert(false);
  }

  // (14)
  // unique_ptrからリソースを移動する
  std::unique_ptr<int> p14_org(new int(3));
  std::shared_ptr<int> p14 = std::move(p14_org);
  assert(*p14.get() == 3);
  assert(p14.use_count() == 1);
  assert(p14_org.get() == nullptr);

  // (15)
  // 空のshared_ptrを構築する
  std::shared_ptr<int> p15 = nullptr;
  assert(p15.get() == nullptr);
  assert(p15.use_count() == 0);
}

出力

バージョン

言語

  • C++11

処理系

  • Clang: 3.0
  • GCC: 4.3.6 (unique_ptr, nullptr以外), 4.4.7 (nullptr以外), 4.6.4
  • ICC: ??
  • Visual C++: 2008 (TR1), 2010, 2012, 2013
    • 2008は(1), (2), (3), (4), (8), (9), (12), (13)のみ
    • 2008, 2010の(13)は、仮引数の型がauto_ptr<Y>&&ではなくauto_ptr<Y>&になっている。

参照