std::unique_ptr<T,Deleter>::unique_ptr
Declarations
- Primary Template, unique_ptr<T>
- Specialization for Arrays, unique_ptr<T[]>
- C++23
- C++17
- C++11
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
constexpr explicit unique_ptr( pointer p ) noexcept;
// 3)
constexpr unique_ptr( pointer p, /* see below */ d1 ) noexcept;
// 4)
constexpr unique_ptr( pointer p, /* see below */ d2 ) noexcept;
// 5)
constexpr unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
constexpr unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
explicit unique_ptr( pointer p ) noexcept;
// 3)
unique_ptr( pointer p, /* see below */ d1 ) noexcept;
// 4)
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
// 5)
unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
explicit unique_ptr( pointer p ) noexcept;
// 3)
unique_ptr( pointer p, /* see below */ d1 ) noexcept;
// 4)
unique_ptr( pointer p, /* see below */ d2 ) noexcept;
// 5)
unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 7)
template< class U >
unique_ptr( std::auto_ptr<U>&& u ) noexcept;
- C++23
- C++11
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
template< class U >
constexpr explicit unique_ptr( U p ) noexcept;
// 3)
template< class U >
constexpr unique_ptr( U p, /* see below */ d1 ) noexcept;
// 4)
template< class U >
constexpr unique_ptr( U p, /* see below */ d2 ) noexcept;
// 5)
constexpr unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
constexpr unique_ptr( unique_ptr<U, E>&& u ) noexcept;
// 1)
constexpr unique_ptr() noexcept;
constexpr unique_ptr( std::nullptr_t ) noexcept;
// 2)
template< class U >
explicit unique_ptr( U p ) noexcept;
// 3)
template< class U >
unique_ptr( U p, /* see below */ d1 ) noexcept;
// 4)
template< class U >
unique_ptr( U p, /* see below */ d2 ) noexcept;
// 5)
unique_ptr( unique_ptr&& u ) noexcept;
// 6)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;
Description
1)
Constructs a std::unique_ptr
that owns nothing. Value-initializes the stored pointer and the stored deleter.
Requires that Deleter
is DefaultConstructible
and that construction does not throw an exception.
These overloads participate in overload resolution only if std::is_default_constructible<Deleter>::value
is true
and Deleter
is not a pointer type.
2)
Constructs a std::unique_ptr
which owns p
, initializing the stored pointer with p
and value-initializing the stored deleter.
Requires that Deleter
is DefaultConstructible
and that construction does not throw an exception.
This overload participates in overload resolution only if std::is_default_constructible<Deleter>::value
is true
and Deleter
is not a pointer type.
This constructor is not selected by class template argument deduction.(since C++17)
3-4)
Constructs a std::unique_ptr
object which owns p
, initializing the stored pointer with p
and initializing a deleter D
as below
(depends upon whether D
is a reference type):
-
If
D
is non-reference typeA
, then the signatures are:unique_ptr(pointer p, const A& d) noexcept; (1) (requires that
Deleter
is nothrow-CopyConstructible)
unique_ptr(pointer p, A&& d) noexcept; (2) (requires thatDeleter
is nothrow-MoveConstructible) -
If
D
is an lvalue-reference typeA&
, then the signatures are:unique_ptr(pointer p, A& d) noexcept; (1)
unique_ptr(pointer p, A&& d) = delete; (2) -
If
D
is an lvalue-reference typeconst A&
, then the signatures are:unique_ptr(pointer p, const A& d) noexcept; (1)
unique_ptr(pointer p, const A&& d) = delete; (2)
In all cases the deleter is initialized from std::forward<decltype(d)>(d)
.
These overloads participate in overload resolution only if std::is_constructible<D, decltype(d)>::value
is true
.
These two constructors are not selected by class template argument deduction.(since C++17)
2-4)
In the specialization for arrays behave the same as the constructors that take a pointer parameter in the primary template except that they additionally do not participate in overload resolution unless one of the following is true:
U
is the same type as pointer, orU
isstd::nullptr_t
, or- pointer is the same type as
element_type*
andU
is some pointer typeV*
such thatV(*)[]
is implicitly convertible toelement_type(*)[]
.
5)
Constructs a unique_ptr
by transferring ownership from u
to *this
and stores the null
pointer in u
.
This constructor only participates in overload resolution if std::is_move_constructible<Deleter>::value
is true
. If Deleter
is not a reference type,
requires that it is nothrow-MoveConstructible (if Deleter
is a reference, get_deleter()
and u.get_deleter()
after move construction reference the same value)
6)
Constructs a unique_ptr
by transferring ownership from u
to *this
, where u
is constructed with a specified deleter (E)
.
It depends upon whether E
is a reference type, as following:
- if
E
is a reference type, this deleter is copy constructed fromu
's deleter (requires that this construction does not throw) - if
E
is a non-reference type, this deleter is move constructed fromu
's deleter (requires that this construction does not throw)
This constructor only participates in overload resolution if all of the following is true:
unique_ptr<U, E>::pointer
is implicitly convertible to pointerU
is not an array type- Either
Deleter
is a reference type andE
is the same type asD
, orDeleter
is not a reference type andE
is implicitly convertible toD
7)
Constructs a unique_ptr
where the stored pointer is initialized with u.release()
and the stored deleter is value-initialized.
This constructor only participates in overload resolution if U*
is implicitly convertible to T*
and Deleter
is the same type as std::default_delete<T>
.
Parameters
p
- a pointer to an object to manage
d1
,d2
- a deleter to use to destroy the object
u
- another smart pointer to acquire the ownership from
Notes
Instead of using the overload (2) together with new, it is often a better idea to use
std::make_unique<T>
. (since C++14)
std::unique_ptr<Derived>
is implicitly convertible to std::unique_ptr<Base>
through the overload (6)
(because both the managed pointer and std::default_delete
are implicitly convertible)
Because the default constructor is constexpr
, static unique_ptrs
are initialized as part of static non-local initialization,
before any dynamic non-local initialization begins. This makes it safe to use a unique_ptr
in a constructor of any static object.
There is no class template argument deduction from pointer type because it is impossible to distinguish a pointer obtained from array and non-array forms of new. (since C++17)
Examples
#include <iostream>
#include <memory>
struct Foo { // object to manage
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 { // deleter
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 is empty
std::unique_ptr<Foo> up1b(nullptr); // up1b is empty
std::cout << "Example constructor(2)...\n";
{
std::unique_ptr<Foo> up2(new Foo); //up2 now owns a Foo
} // Foo deleted
std::cout << "Example constructor(3)...\n";
D d;
{ // deleter type is not a reference
std::unique_ptr<Foo, D> up3(new Foo, d); // deleter copied
}
{ // deleter type is a reference
std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b holds a reference to d
}
std::cout << "Example constructor(4)...\n";
{ // deleter is not a reference
std::unique_ptr<Foo, D> up4(new Foo, D()); // deleter moved
}
std::cout << "Example constructor(5)...\n";
{
std::unique_ptr<Foo> up5a(new Foo);
std::unique_ptr<Foo> up5b(std::move(up5a)); // ownership transfer
}
std::cout << "Example constructor(6)...\n";
{
std::unique_ptr<Foo, D> up6a(new Foo, d); // D is copied
std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D is moved
std::unique_ptr<Foo, D&> up6c(new Foo, d); // D is a reference
std::unique_ptr<Foo, D> up6d(std::move(up6c)); // D is copied
}
#if (__cplusplus < 201703L)
std::cout << "Example constructor(7)...\n";
{
std::auto_ptr<Foo> up7a(new Foo);
std::unique_ptr<Foo> up7b(std::move(up7a)); // ownership transfer
}
#endif
std::cout << "Example array constructor...\n";
{
std::unique_ptr<Foo[]> up(new Foo[3]);
} // three Foo objects deleted
}
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