std::unique_ptr::unique_ptr

From cppreference.com
< cpp‎ | memory‎ | unique ptr
 
 
 
 
 
members of the primary template, unique_ptr<T>
constexpr unique_ptr();
constexpr unique_ptr( nullptr_t );
(1)
explicit unique_ptr( pointer p );
(2)
unique_ptr( pointer p, /* see below */ d1 );
(3)
unique_ptr( pointer p, /* see below */ d2 );
(4)
unique_ptr( unique_ptr&& u );
(5)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u );
(6)
template< class U >
unique_ptr( auto_ptr<U>&& u );
(7) (until C++17)
members of the specialization for arrays, unique_ptr<T[]>
constexpr unique_ptr();
constexpr unique_ptr( nullptr_t );
(1)
explicit unique_ptr( pointer p );
(2) (until C++17)
template<class U> explicit unique_ptr( U p );
(2) (since C++17)
unique_ptr( pointer p, /* see below */ d1 );
(3) (until C++17)
template<class U> unique_ptr( U p, /* see below */ d1 );
(3) (since C++17)
unique_ptr( pointer p, /* see below */ d2 );
(4) (until C++17)
template<class U> unique_ptr( U p, /* see below */ d2 );
(4) (since C++17)
unique_ptr( unique_ptr&& u );
(5)
template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u );
(6) (since C++17)
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.
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.
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)
a) If D is non-reference type A, then the signatures are:
unique_ptr(pointer p, const A& d); (requires that Deleter is nothrow-CopyConstructible)
unique_ptr(pointer p, A&& d); (requires that Deleter is nothrow-MoveConstructible)
b) If D is an lvalue-reference type A&, then the signatures are:
unique_ptr(pointer p, A& d);
unique_ptr(pointer p, A&& d);
c) If D is an lvalue-reference type const A&, then the signatures are:
unique_ptr(pointer p, const A& d);
unique_ptr(pointer p, const A&& d);
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 will only participate in overload resolution if either
U is the same type as pointer, or
pointer is the same type as element_type* and U is some pointer type V* such that V(*)[] is implicitly convertible to element_type(*)[].
(since C++17)
5) Constructs a unique_ptr by transferring ownership from u to *this. 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:
a) if E is a reference type, this deleter is copy constructed from u's deleter (requires that this construction does not throw)
b) if E is a non-reference type, this deleter is move constructed from u's deleter (requires that this construction does not throw)
This constructor only participates in overload resolution if all of the following is true:
a) unique_ptr<U, E>::pointer is implicitly convertible to pointer
b) U is not an array type
c) Either Deleter is a reference type and E is the same type as D, or Deleter is not a reference type and E is implicitly convertible to D
6) in the specialization for arrays behaves the same as in the primary template, except that it will only participate in overload resolution if all of the following is true
U is an array type
pointer is the same type as element_type*
unique_ptr<U,E>::pointer is the same type as unique_ptr<U,E>::element_type*
unique_ptr<U,E>::element_type(*)[] is convertible to element_type(*)[]
either Deleter is a reference type and E is the same type as Deleter, or Deleter is not a reference type and E is implicitly convertible to Deleter.
(since C++17)
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>.

Contents

[edit] 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

[edit] Exceptions

noexcept specification:  
noexcept
  

[edit] Notes

Instead of using the overload (2) together with new, it is often a better idea to use std::make_unique<T>.

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)

[edit] Example

#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
    }
 
    std::cout << "Example constructor(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::move(up7a)); // ownership transfer
    }
}

Output:

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