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
が配列型ではないこと。D
とE
が同じ型であること。もしくは参照型ではないD
において、E
がD
に暗黙的に変換可能な型であること。
C++17 共通
- (1), (2), (6) : 以下のいずれかの条件を満たす場合、オーバーロード解決に参加しない。
is_pointer_v<deleter_type>== true
である(デリータがポインタである)is_default_constructible_v<deleter_type> == false
である(デリータがデフォルト構築できない)
- (3), (4) :
is_constructible_v<D, decltype(d)>== true
の(d
からコピー/ムーブ構築可能な)場合にのみオーバーロード解決に参加する。 - (3), (4), (6) : クラステンプレートの実引数推定によってこれらのコンストラクタが選択される場合、コンパイルエラーとなる。
C++17 配列版
- (2), (3), (4) : 以下のいずれかの場合にのみオーバーロード解決に参加する:
U
はメンバ型pointer
と同じ型pointer
はelement_type*
と同じ型かつU
は何らかのポインタ型V*
であり、V(*)[]
はelement_type(*)[]
に変換可能であるU
はnullptr_t
である((3), (4)のみ)
- (7) : 以下の全ての条件を満たさない場合、この関数はオーバーロード解決の候補から外れる:
U
は配列型ではないことpointer
はelement_type*
と同じ型unique_ptr<U, E>::pointer
はunique_ptr<U, E>::element_type*
と同じ型unique_ptr<U, E>::element_type(*)[]
はelement_type(*)[]
に変換可能であるD
とE
は同じ型で共に参照型である、もしくはD
は参照型ではなくE
はD
に暗黙変換可能である
効果
- (1) : 値初期化したポインタとデリータオブジェクトを、メンバ変数に保持する。
- (2) : ポインタ
p
と値初期化したデリータオブジェクトを、メンバ変数に保持する。 - (3) : ポインタ
p
とデリータオブジェクトd1
を、メンバ変数に保持する。 - (4) : ポインタ
p
と、d2
からムーブしたデリータオブジェクトd2
を、メンバ変数に保持する。 - (5) :
u
が持つポインタの所有権を、*this
に譲渡する。デリータオブジェクトは、可能であればムーブし、そうでなければコピーする。 - (6) : (1)と同じく、値初期化したポインタとデリータオブジェクトを、メンバ変数に保持する。
- (7) : (5)と同じく、
u
が持つポインタの所有権を、*this
に譲渡する。デリータオブジェクトは、可能であればムーブし、そうでなければコピーする。 - (8) :
u.release()
の戻り値である所有権が放棄されたポインタと、値初期化したデリータオブジェクトを、メンバ変数に保持する。
例外
投げない
備考
- (3) : デリータの型
D
がD&
のように左辺値参照の形式の場合、このコンストラクタのデリータパラメータは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で宣言のみ行う手法で代用されている。
関連項目
参照
- N2435 Explicit bool for Smart Pointers
- (6)の経緯となる提案文書
- N4190 Removing
auto_ptr
,random_shuffle()
, And Old<functional>
Stuff - N4089 Safe conversions in
unique_ptr<T[]>
, revision 2 - LWG Issue 2520 : N4089 broke initializing
unique_ptr<T[]>
from a nullptr - LWG Issue 2801. Default-constructibility of
unique_ptr
- LWG Issue 2905.
is_constructible_v<unique_ptr<P, D>, P, D const &>
should be false when D is not copy constructible - P2273R3 Making
std::unique_ptr
constexpr