std::unique_ptr<T,Deleter>::unique_ptr - cppreference.com
提供: cppreference.com
<tbody> </tbody>
| プライマリテンプレート unique_ptr<T> のメンバ |
||
|
|
(1) | |
|
|
(2) | |
|
|
(3) | |
|
|
(4) | |
|
|
(5) | |
|
|
(6) | |
|
|
(7) | (C++17で削除) |
| 配列に対する特殊化 unique_ptr<T[]> のメンバ |
||
|
|
(1) | |
|
|
(2) | (C++17未満) |
|
|
(2) | (C++17以上) |
|
|
(3) | (C++17未満) |
|
|
(3) | (C++17以上) |
|
|
(4) | (C++17未満) |
|
|
(4) | (C++17以上) |
|
|
(5) | |
|
|
(6) | (C++17以上) |
1) 何も所有しない std::unique_ptr を構築します。 格納されるポインタおよび格納されるデリータは値初期化されます。 Deleter が DefaultConstructible であり、その構築が例外を投げないことが要求されます。
|
|
(C++17未満) |
|
これらのオーバーロードは、 |
(C++17以上) |
2) p を所有する std::unique_ptr を構築します。 格納されるポインタは p で初期化され、格納されるデリータは値初期化されます。 Deleter が DefaultConstructible であり、その構築が例外を投げないことが要求されます。
|
|
(C++17未満) |
|
このオーバーロードは、 |
(C++17以上) |
3-4) p を所有する std::unique_ptr を構築します。 格納されるポインタは p で初期化され、デリータ D は (D が参照型かどうかに依存して) 以下のように初期化されます。
a) D が参照でない型 A の場合、シグネチャは以下のようになります。
<tbody>
</tbody>
|
|
(1) | (Deleter が nothrow-CopyConstructible であることが要求されます) |
|
|
(2) | (Deleter が nothrow-MoveConstructible であることが要求されます) |
b) D が左辺値参照型 A& の場合、シグネチャは以下のようになります。
<tbody>
</tbody>
|
|
(1) | |
|
|
(2) | |
c) D が左辺値参照型 const A& の場合、シグネチャは以下のようになります。
<tbody>
</tbody>
|
|
(1) | |
|
|
(2) | |
いずれの場合も、デリータは std::forward<decltype(d)>(d) から初期化されます。
|
|
(C++17未満) |
|
|
(C++17以上) |
|
2-4) 配列に対する特殊化では、プライマリテンプレートのポインタ引数を取るコンストラクタと同じように動作します。 ただし、以下のいずれかが真でなければ、これらはオーバーロード解決に参加しません。
|
(C++17以上) |
5) u から *this に所有権を転送することによって unique_ptr を構築し、 u にヌルポインタを格納します。 このコンストラクタは、 std::is_move_constructible<Deleter>::value が true の場合にのみ、オーバーロード解決に参加します。 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>::pointer が pointer に暗黙に変換可能である
b) U が配列型でない
c) Deleter が参照型であり E が D 同じである、または、 Deleter が参照型でなく E が D に暗黙に変換可能である
|
6) 配列に対する特殊化では、プライマリテンプレートと同じように動作します。 ただし、以下の条件がすべて真の場合にのみ、オーバーロード解決に参加します。
|
(C++17以上) |
7) unique_ptr を構築します。 格納されるポインタは u.release() で初期化され、格納されるデリータは値初期化されます。 このコンストラクタは、 U* が T* に暗黙に変換可能であり、 Deleter が std::default_delete<T> と同じ型である場合にのみ、オーバーロード解決に参加します。
引数
| p | - | 管理するオブジェクトを指すポインタ |
| d1,d2 | - | オブジェクトを破棄するために使用するデリータ |
| u | - | 所有権を取得する別のスマートポインタ |
ノート
オーバーロード (2) を new と一緒に使うよりも std::make_unique を使う方が、通常、より良い考えです。
std::unique_ptr<Derived> はオーバーロード (6) を通して std::unique_ptr<Base> に暗黙に変換可能です (管理対象ポインタおよび std::default_delete はどちらも暗黙に変換可能なため)。
デフォルトコンストラクタが constexpr であるため、 static な unique_ptr は、いかなる動的非ローカル初期化が始まるよりも前に、静的非ローカル初期化の一部として初期化されます。 このため、 static オブジェクトのコンストラクタで unique_ptr を使用しても安全です。
|
配列形式の |
(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