名前空間
変種
操作

std::unique_ptr<T,Deleter>::unique_ptr

提供: cppreference.com
< cpp‎ | memory‎ | unique ptr
 
 
 
動的メモリ管理
スマートポインタ
(C++11)
(C++11)
(C++11)
(C++17未満)
(C++11)
アロケータ
メモリリソース
未初期化記憶域
(C++17)
ガベージコレクションサポート
その他
(C++20)
(C++11)
(C++11)
C のライブラリ
低水準のメモリ管理
 
 
プライマリテンプレート unique_ptr<T> のメンバ
constexpr unique_ptr() noexcept;
constexpr unique_ptr( nullptr_t ) noexcept;
(1)
explicit unique_ptr( pointer p ) noexcept;
(2)
unique_ptr( pointer p, /* see below */ d1 ) noexcept;
(3)
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
(4)
unique_ptr( unique_ptr&& u ) noexcept;
(5)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
(6)
template< class U >
unique_ptr( std::auto_ptr<U>&& u ) noexcept;
(7) (C++17で削除)
配列に対する特殊化 unique_ptr<T[]> のメンバ
constexpr unique_ptr() noexcept;
constexpr unique_ptr( nullptr_t ) noexcept;
(1)
explicit unique_ptr( pointer p ) noexcept;
(2) (C++17未満)
template<class U> explicit unique_ptr( U p ) noexcept;
(2) (C++17以上)
unique_ptr( pointer p, /* see below */ d1 ) noexcept;
(3) (C++17未満)
template<class U> unique_ptr( U p, /* see below */ d1 ) noexcept;
(3) (C++17以上)
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
(4) (C++17未満)
template<class U> unique_ptr( U p, /* see below */ d2 ) noexcept;
(4) (C++17以上)
unique_ptr( unique_ptr&& u ) noexcept;
(5)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
(6) (C++17以上)
1) 何も所有しない std::unique_ptr を構築します。 格納されるポインタおよび格納されるデリータは値初期化されます。 DeleterDefaultConstructible であり、その構築が例外を投げないことが要求されます。

Deleter がポインタ型または参照型の場合、このコンストラクタは ill-formed です。

(C++17未満)

これらのオーバーロードは、std::is_default_constructible<Deleter>::valuetrue であり、 Deleter がポインタ型でない場合にのみ、オーバーロード解決に参加します。

(C++17以上)
2) p を所有する std::unique_ptr を構築します。 格納されるポインタは p で初期化され、格納されるデリータは値初期化されます。 DeleterDefaultConstructible であり、その構築が例外を投げないことが要求されます。

Deleter がポインタ型または参照型の場合、このコンストラクタは ill-formed です。

(C++17未満)

このオーバーロードは、std::is_default_constructible<Deleter>::valuetrue であり、 Deleter がポインタ型でない場合にのみ、オーバーロード解決に参加します。 クラステンプレートの実引数推定によってこのコンストラクタが選択された場合、プログラムは ill-formed です。

(C++17以上)
3-4) p を所有する std::unique_ptr を構築します。 格納されるポインタは p で初期化され、デリータ D は (D が参照型かどうかに依存して) 以下のように初期化されます。
a) D が参照でない型 A の場合、シグネチャは以下のようになります。
unique_ptr(pointer p, const A& d) noexcept;
(1) (Deleter が nothrow-CopyConstructible であることが要求されます)
unique_ptr(pointer p, A&& d) noexcept;
(2) (Deleter が nothrow-MoveConstructible であることが要求されます)
b) D が左辺値参照型 A& の場合、シグネチャは以下のようになります。
unique_ptr(pointer p, A& d) noexcept;
(1)
unique_ptr(pointer p, A&& d);
(2)
c) D が左辺値参照型 const A& の場合、シグネチャは以下のようになります。
unique_ptr(pointer p, const A& d) noexcept;
(1)
unique_ptr(pointer p, const A&& d);
(2)
いずれの場合も、デリータは std::forward<decltype(d)>(d) から初期化されます。

D が参照型で、2番目のオーバーロードが選択された場合、プログラムは ill-formed です。

(C++17未満)

D が参照型の場合、2番目のオーバーロードは削除されたものとして定義されます。 これらのオーバーロードは、std::is_constructible<D, decltype(d)>::valuetrue である場合にのみ、オーバーロード解決に参加します。 クラステンプレートの実引数推定によってこれら2つのコンストラクタのいずれかが選択された場合、プログラムは ill-formed です。

(C++17以上)
2-4) 配列に対する特殊化では、プライマリテンプレートのポインタ引数を取るコンストラクタと同じように動作します。 ただし、以下のいずれかが真でなければ、これらはオーバーロード解決に参加しません。
  • Upointer と同じ型である
  • Ustd::nullptr_t である
  • pointerelement_type* と同じ型であり、 U が何らかのポインタ型 V* であり、 V(*)[]element_type(*)[] に暗黙に変換可能である
(C++17以上)
5) u から *this に所有権を転送することによって unique_ptr を構築し、 u にヌルポインタを格納します。 このコンストラクタは、 std::is_move_constructible<Deleter>::valuetrue の場合にのみ、オーバーロード解決に参加します。 Deleter が参照型でなければ、 nothrow-MoveConstructible であることが要求されます (Deleter が参照型の場合は、ムーブ構築後 get_deleter() および u.get_deleter() は同じ値を参照します)。
6) u から *this に所有権を転送することによって unique_ptr を構築します。 ただし u は指定されたデリータ (E) を使用して構築されます。 これは以下のように、 E が参照型かどうかに依存します。
a) E が参照型であれば、このデリータは u のデリータからコピー構築されます (この構築が例外を投げないことが要求されます)。
b) E が参照型でなければ、このデリータは u のデリータからムーブ構築されます (この構築が例外を投げないことが要求されます)。
このコンストラクタは、以下の条件がすべて真の場合にのみ、オーバーロード解決に参加します。
a) unique_ptr<U, E>::pointerpointer に暗黙に変換可能である
b) U が配列型でない
c) Deleter が参照型であり ED 同じである、または、 Deleter が参照型でなく ED に暗黙に変換可能である
6) 配列に対する特殊化では、プライマリテンプレートと同じように動作します。 ただし、以下の条件がすべて真の場合にのみ、オーバーロード解決に参加します。
  • U が配列型である
  • pointerelement_type* と同じ型である
  • unique_ptr<U,E>::pointerunique_ptr<U,E>::element_type* と同じ型である
  • unique_ptr<U,E>::element_type(*)[]element_type(*)[] に変換可能である
  • Deleter が参照型であり EDeleter と同じ型である、または、 Deleter が参照型でなく EDeleter に暗黙に変換可能である
(C++17以上)
7) unique_ptr を構築します。 格納されるポインタは u.release() で初期化され、格納されるデリータは値初期化されます。 このコンストラクタは、 U*T* に暗黙に変換可能であり、 Deleterstd::default_delete<T> と同じ型である場合にのみ、オーバーロード解決に参加します。

[編集] 引数

p - 管理するオブジェクトを指すポインタ
d1,d2 - オブジェクトを破棄するために使用するデリータ
u - 所有権を取得する別のスマートポインタ

[編集] ノート

オーバーロード (2) を new と一緒に使うよりも std::make_unique<T> を使う方が、通常、より良い考えです。

std::unique_ptr<Derived> はオーバーロード (6) を通して std::unique_ptr<Base> に暗黙に変換可能です (管理対象ポインタおよび std::default_delete はどちらも暗黙に変換可能なため)。

デフォルトコンストラクタが constexpr であるため、 static な unique_ptr は、いかなる動的非ローカル初期化が始まるよりも前に、静的非ローカル初期化の一部として初期化されます。 このため、 static オブジェクトのコンストラクタで unique_ptr を使用しても安全です。

配列形式の new と非配列形式の new のどちらから取得したポインタか区別することはできないため、ポインタ型からのクラステンプレートの実引数推定はありません。

(C++17以上)

[編集]

#include <iostream>
#include <memory>
 
struct Foo { // 管理するオブジェクト。
    Foo() { std::cout << "Foo ctor\n"; }
    Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
    Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
    ~Foo() { std::cout << "~Foo dtor\n"; }
};
 
struct D { // デリータ。
    D() {};
    D(const D&) { std::cout << "D copy ctor\n"; }
    D(D&) { std::cout << "D non-const copy ctor\n";}
    D(D&&) { std::cout << "D move ctor \n"; }
    void operator()(Foo* p) const {
        std::cout << "D is deleting a Foo\n";
        delete p;
    };
};
 
int main()
{
    std::cout << "Example constructor(1)...\n";
    std::unique_ptr<Foo> up1;  // up1 は空です。
    std::unique_ptr<Foo> up1b(nullptr);  // up1b は空です。
 
    std::cout << "Example constructor(2)...\n";
    {
        std::unique_ptr<Foo> up2(new Foo); // up2 は Foo を保持します。
    } // Foo が削除されます。
 
    std::cout << "Example constructor(3)...\n";
    D d;
    {  // デリータの型が参照でない。
       std::unique_ptr<Foo, D> up3(new Foo, d); // デリータはコピーされます。
    }
    {  // デリータの型が参照。
       std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b は d への参照を保持します。
    }
 
    std::cout << "Example constructor(4)...\n";
    {  // デリータが参照でない。
       std::unique_ptr<Foo, D> up4(new Foo, D()); // デリータはムーブされます。
    }
 
    std::cout << "Example constructor(5)...\n";
    {
       std::unique_ptr<Foo> up5a(new Foo);
       std::unique_ptr<Foo> up5b(std::move(up5a)); // 所有権の転送。
    }
 
    std::cout << "Example constructor(6)...\n";
    {
        std::unique_ptr<Foo, D> up6a(new Foo, d); // D はコピーされます。
        std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D はムーブされます。
 
        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D は参照です。
        std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D はコピーされます。
    }
 
#if (__cplusplus < 201703L)
    std::cout << "Example constructor(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::move(up7a)); // 所有権の転送。
    }
#endif
 
    std::cout << "Example array constructor...\n";
    {
        std::unique_ptr<Foo[]> up(new Foo[3]);
    } // 3個の Foo オブジェクトが削除されます。
}

出力:

Example constructor(1)...
Example constructor(2)...
Foo ctor
~Foo dtor
Example constructor(3)...
Foo ctor
D copy ctor
D is deleting a Foo
~Foo dtor
Foo ctor
D is deleting a Foo
~Foo dtor
Example constructor(4)...
Foo ctor
D move ctor 
D is deleting a Foo
~Foo dtor
Example constructor(5)...
Foo ctor
~Foo dtor
Example constructor(6)...
Foo ctor
D copy ctor
D move ctor 
Foo ctor
D non-const copy ctor
D is deleting a Foo
~Foo dtor
D is deleting a Foo
~Foo dtor
Example constructor(7)...
Foo ctor
~Foo dtor
Example array constructor...
Foo ctor
Foo ctor
Foo ctor
~Foo dtor
~Foo dtor
~Foo dtor