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
Dis non-reference typeA, then the signatures are:unique_ptr(pointer p, const A& d) noexcept; (1) (requires that
Deleteris nothrow-CopyConstructible)
unique_ptr(pointer p, A&& d) noexcept; (2) (requires thatDeleteris nothrow-MoveConstructible) -
If
Dis 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
Dis 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:
Uis the same type as pointer, orUisstd::nullptr_t, or- pointer is the same type as
element_type*andUis 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
Eis a reference type, this deleter is copy constructed fromu's deleter (requires that this construction does not throw) - if
Eis 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>::pointeris implicitly convertible to pointerUis not an array type- Either
Deleteris a reference type andEis the same type asD, orDeleteris not a reference type andEis 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