• Class / Function / Type

      std::
    • Header file

      <>
    • Other / All

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

    履歴 編集

    function
    <memory>

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

    constexpr unique_ptr() noexcept;             // (1) 単一オブジェクト、配列
    
    explicit unique_ptr(pointer p) noexcept;           // (2) 単一オブジェクト、配列(C++14まで)
    constexpr explicit unique_ptr(pointer p) noexcept; // (2) 単一オブジェクト C++23
    template<class U>
    explicit unique_ptr(U p) noexcept;                 // (2) 配列 C++17
    template<class U>
    constexpr explicit unique_ptr(U p) noexcept;       // (2) 配列 C++23
    
    unique_ptr(pointer p, const D& d1) noexcept;           // (3) 単一オブジェクト、配列(C++14まで)
    constexpr unique_ptr(pointer p, const D& d1) noexcept; // (3) 単一オブジェクト C++23
    template<class U>
    unique_ptr(U p, const D& d1) noexcept;                 // (3) 配列 C++17
    template<class U>
    constexpr unique_ptr(U p, const D& d1) noexcept;       // (3) 配列 C++23
    
    unique_ptr(pointer p, D&& d2) noexcept;           // (4) 単一オブジェクト、配列(C++14まで)
    constexpr unique_ptr(pointer p, D&& d2) noexcept; // (4) 単一オブジェクト C++23
    template<class U>
    unique_ptr(U p, D&& d2) noexcept;                 // (4) 配列 C++17
    template<class U>
    constexpr unique_ptr(U p, D&& d2) noexcept;       // (4) 配列 C++23
    
    unique_ptr(unique_ptr&& u) noexcept;           // (5) 単一オブジェクト、配列
    constexpr unique_ptr(unique_ptr&& u) noexcept; // (5) 単一オブジェクト、配列 C++23
    
    constexpr unique_ptr(nullptr_t) noexcept;    // (6) 単一オブジェクト、配列
    
    template <class U, class E>
    unique_ptr(unique_ptr<U, E>&& u) noexcept;   // (7) 単一オブジェクト、配列(C++17)
    template <class U, class E>
    constexpr unique_ptr(unique_ptr<U, E>&& u) noexcept; // (7) 単一オブジェクト、配列 C++23
    
    template <class U>
    unique_ptr(auto_ptr<U>&& u) noexcept;        // (8) 単一オブジェクト
                                                 // C++11から非推奨
                                                 // C++17で削除
    
    unique_ptr(const unique_ptr&) = delete;      // (9) 単一オブジェクト、配列
    

    unique_ptrオブジェクトの構築

    • (1) : デフォルトコンストラクタ。所有権を持たない、空のunique_ptrオブジェクトを構築する。
    • (2) : 生ポインタの所有権を受け取る。
    • (3), (4) : 生ポインタの所有権、およびデリータオブジェクトを受け取る。デリータオブジェクトはforwardされる。
    • (5) : ムーブコンストラクタ。uから*thisに、所有権を譲渡する。
    • (6) : デフォルトコンストラクタと同じく、所有権を持たない、空のunique_ptrオブジェクトを構築する。
    • (7) : 変換可能なポインタ型を持つunique_ptrオブジェクトからの変換。
    • (8) : 変換可能なポインタ型を持つauto_ptrオブジェクトからの変換。
    • (9) : コピー構築禁止。

    要件

    • (1), (2) : デリータの型Dが、例外を投げずにデフォルト構築可能であること。
    • (3) : デリータの型Dが、例外を投げずにコピー構築可能であること。
    • (4), (5) : デリータの型Dが、例外を投げずにムーブ構築可能であること。
    • (6) : デリータの型Dが、例外を投げずにデフォルト構築可能であること。
    • (7) : 以下の条件を満たさない場合、この関数はオーバーロード解決の候補から外れる:
      • unique_ptr<U, E>::pointerが、pointerに暗黙変換可能な型であること。
      • Uが配列型ではないこと。
      • DEが同じ型であること。もしくは参照型ではないDにおいて、EDに暗黙的に変換可能な型であること。

    C++17 共通

    C++17 配列版

    • (2), (3), (4) : 以下のいずれかの場合にのみオーバーロード解決に参加する:
      • Uはメンバ型pointerと同じ型
      • pointerelement_type*と同じ型かつUは何らかのポインタ型V*であり、V(*)[]element_type(*)[]に変換可能である
      • Unullptr_tである((3), (4)のみ)
    • (7) : 以下の全ての条件を満たさない場合、この関数はオーバーロード解決の候補から外れる:
      • Uは配列型ではないこと
      • pointerelement_type*と同じ型
      • unique_ptr<U, E>::pointerunique_ptr<U, E>::element_type*と同じ型
      • unique_ptr<U, E>::element_type(*)[]element_type(*)[]に変換可能である
      • DEは同じ型で共に参照型である、もしくはDは参照型ではなくEDに暗黙変換可能である

    効果

    • (1) : 値初期化したポインタとデリータオブジェクトを、メンバ変数に保持する。
    • (2) : ポインタp値初期化したデリータオブジェクトを、メンバ変数に保持する。
    • (3) : ポインタpとデリータオブジェクトd1を、メンバ変数に保持する。
    • (4) : ポインタpと、d2からムーブしたデリータオブジェクトd2を、メンバ変数に保持する。
    • (5) : uが持つポインタの所有権を、*thisに譲渡する。デリータオブジェクトは、可能であればムーブし、そうでなければコピーする。
    • (6) : (1)と同じく、値初期化したポインタとデリータオブジェクトを、メンバ変数に保持する。
    • (7) : (5)と同じく、uが持つポインタの所有権を、*thisに譲渡する。デリータオブジェクトは、可能であればムーブし、そうでなければコピーする。
    • (8) : u.release()戻り値である所有権が放棄されたポインタと、値初期化したデリータオブジェクトを、メンバ変数に保持する。

    例外

    投げない

    備考

    • (3) : デリータの型DD&のように左辺値参照の形式の場合、このコンストラクタのデリータパラメータはD&型となる。

    D deleter;
    unique_ptr<T, D&> p(new T(), deleter); // pはdeleterへの参照を保持する
    

    #include <cassert>
    #include <memory>
    
    using AllocTraits = std::allocator_traits<std::allocator<int>>;
    
    class Deleter {
     public:
      explicit Deleter(const std::allocator<int>& alloc) : alloc_(alloc) {}
    
      void operator()(int* p) {
        AllocTraits::destroy(alloc_, p);
        AllocTraits::deallocate(alloc_, p, 1);
      }
     private:
      std::allocator<int> alloc_;
    };
    
    int main()
    {
      // (1) デフォルト構築
      // 所有権を持たない、空のunique_ptrオブジェクトを構築する
      std::unique_ptr<int> p1;
      assert(!p1);
    
      // (2) 生ポインタから所有権を譲渡して構築
      std::unique_ptr<int> p2(new int(3));
      assert(p2);
    
      // (3), (4) 生ポインタから所有権を譲渡し、デリータオブジェクトとともに構築
      std::unique_ptr<int> p3(new int(3), std::default_delete<int>());
      assert(p3);
    
      // 自作デリータを使った例
      {
        std::allocator<int> alloc;
        int* p = AllocTraits::allocate(alloc, 1);
        AllocTraits::construct(alloc, p, 4);
        std::unique_ptr<int, Deleter> p4(p, Deleter(alloc));
        assert(p4);
        assert(*p4 == 4);
      }
    
      // (5) 他のunique_ptrから所有権を譲渡する
      std::unique_ptr<int> p5 = std::move(p3);
      assert(*p5 == 3);
    
      // (6) nullptrで構築
      // デフォルトコンストラクタ(1)と同じ
      std::unique_ptr<int> p6 = nullptr;
      assert(!p6);
    
      // (7) 変換可能な他のunique_ptrから所有権を譲渡する
      std::unique_ptr<const int> p7 = std::move(p5);
      assert(*static_cast<const int*>(p7.get()) == 3);
    }
    

    出力

    バージョン

    言語

    • C++11

    処理系

    • GCC: 4.4.7 (nullptr_tのオーバーロード以外) , 4.6.4
    • Clang: 3.0
    • ICC: ?
    • Visual C++: 2010 , 2012 , 2013
      • 2012までは、delete宣言に対応していないため、代わりにprivateで宣言のみ行う手法で代用されている。

    関連項目

    参照