• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

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

    履歴 編集

    function
    <memory>

    std::shared_ptr::コンストラクタ

    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)  C++14
    
    constexpr shared_ptr(nullptr_t) noexcept;                // (15)  C++17
    
    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オブジェクトを構築する。

    事後条件

    例外

    備考

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

    #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>&になっている。

    参照