std::unique_ptr - cppreference.com

Defined in header

<memory>

template<classT,classDeleter=std::default_delete<T>>classunique_ptr; (1) (since C++11)template<classT,classDeleter>classunique_ptr<T[],Deleter>; (2) (since C++11)std::unique_ptr is a smart pointer that owns (is responsible for) and manages another object via a pointer and subsequently disposes of that object when the unique_ptr goes out of scope.

The object is disposed of, using the associated deleter, when either of the following happens:

the managing unique_ptr object is destroyed.

the managing unique_ptr object is assigned another pointer via

operator=

or

reset()

.

The object is disposed of, using a potentially user-supplied deleter, by calling get_deleter()(ptr). The default deleter (std::default_delete) uses the delete operator, which destroys the object and deallocates the memory.

A unique_ptr may alternatively own no object, in which case it is described as empty.

There are two versions of unique_ptr:

Manages a single object (e.g., allocated with new).

Manages a dynamically-allocated array of objects (e.g., allocated with new[]).

The class satisfies the requirements of

MoveConstructible

and

MoveAssignable

, but of neither

CopyConstructible

nor

CopyAssignable

.

If T* was not a valid type (e.g., T is a reference type), a program that instantiates the definition of std::unique_ptr<T,Deleter> is ill-formed.

Type requirements -Deleter must be

FunctionObject

or lvalue reference to a

FunctionObject

or lvalue reference to function, callable with an argument of type unique_ptr<T,Deleter>::pointer. Notes

Only non-const unique_ptr can transfer the ownership of the managed object to another unique_ptr. If an object's lifetime is managed by a conststd::unique_ptr, it is limited to the scope in which the pointer was created.

unique_ptr is commonly used to manage the lifetime of objects, including:

providing exception safety to classes and functions that handle objects with dynamic lifetime, by guaranteeing deletion on both normal exit and exit through exception.

passing ownership of uniquely-owned objects with dynamic lifetime into functions.

acquiring ownership of uniquely-owned objects with dynamic lifetime from functions.

as the element type in move-aware containers, such as

std::vector

, which hold pointers to dynamically-allocated objects (e.g. if polymorphic behavior is desired).

unique_ptr may be constructed for an

incomplete type

T, such as to facilitate the use as a handle in the

pImpl idiom

. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of unique_ptr. (In contrast,

std::shared_ptr

cannot be constructed from a raw pointer to incomplete type, but can be destroyed where T is incomplete). Note that if T is a class template specialization, use of unique_ptr as an operand, e.g. !p requires T's parameters to be complete due to

ADL

.

If T is a

derived class

of some base B, then unique_ptr<T> is

implicitly convertible

to unique_ptr<B>. The default deleter of the resulting unique_ptr<B> will use

operator delete

for B, leading to

undefined behavior

unless the destructor of B is

virtual

. Note that

std::shared_ptr

behaves differently: std::shared_ptr<B> will use the

operator delete

for the type T and the owned object will be deleted correctly even if the destructor of B is not

virtual

.

Unlike

std::shared_ptr

, unique_ptr may manage an object through any custom handle type that satisfies

NullablePointer

. This allows, for example, managing objects located in shared memory, by supplying a Deleter that defines typedef

boost::offset_ptr

pointer; or another

fancy pointer

.

Feature-test

macroValueStdFeature

__cpp_lib_constexpr_memory

202202L

(C++23)constexpr

std::unique_ptr

Nested types

Type Definition pointerstd::remove_reference<Deleter>::type::pointer if that type exists, otherwise T*. Must satisfy

NullablePointer

element_typeT, the type of the object managed by this unique_ptrdeleter_typeDeleter, the function object or lvalue reference to function or to function object, to be called from the destructor Member functions

(constructor)

constructs a new unique_ptr
(public member function)

[edit]

(destructor)

destructs the managed object if such is present
(public member function)

[edit]

operator=

assigns the unique_ptr
(public member function)

[edit]

Modifiers

release

returns a pointer to the managed object and releases the ownership
(public member function)

[edit]

reset

replaces the managed object
(public member function)

[edit]

swap

swaps the managed objects
(public member function)

[edit]

Observers

get

returns a pointer to the managed object
(public member function)

[edit]

get_deleter

returns the deleter that is used for destruction of the managed object
(public member function)

[edit]

operator bool

checks if there is an associated managed object
(public member function)

[edit]

Single-object version, unique_ptr<T>

operator*operator->

dereferences pointer to the managed object
(public member function)

[edit]

Array version, unique_ptr<T[]>

operator[]

provides indexed access to the managed array
(public member function)

[edit]

Non-member functions

Helper classes

Example

Run this code

#include<cassert>#include<cstdio>#include<fstream>#include<iostream>#include<locale>#include<memory>#include<stdexcept>// helper class for runtime polymorphism demo belowstructB{virtual~B()=default;virtualvoidbar(){std::cout<<"B::bar\n";}};structD:B{D(){std::cout<<"D::D\n";}~D(){std::cout<<"D::~D\n";}voidbar()override{std::cout<<"D::bar\n";}};// a function consuming a unique_ptr can take it by value or by rvalue referencestd::unique_ptr<D>pass_through(std::unique_ptr<D>p){p->bar();returnp;}// helper function for the custom deleter demo belowvoidclose_file(std::FILE*fp){std::fclose(fp);}// unique_ptr-based linked list demostructList{structNode{intdata;std::unique_ptr<Node>next;};std::unique_ptr<Node>head;~List(){// destroy list nodes sequentially in a loop, the default destructor// would have invoked its “next”'s destructor recursively, which would// cause stack overflow for sufficiently large lists.while(head){autonext=std::move(head->next);head=std::move(next);}}voidpush(intdata){head=std::unique_ptr<Node>(newNode{data,std::move(head)});}};intmain(){std::cout<<"1) Unique ownership semantics demo\n";{// Create a (uniquely owned) resourcestd::unique_ptr<D>p=std::make_unique<D>();// Transfer ownership to “pass_through”,// which in turn transfers ownership back through the return valuestd::unique_ptr<D>q=pass_through(std::move(p));// “p” is now in a moved-from 'empty' state, equal to nullptrassert(!p);}std::cout<<"\n""2) Runtime polymorphism demo\n";{// Create a derived resource and point to it via base typestd::unique_ptr<B>p=std::make_unique<D>();// Dynamic dispatch works as expectedp->bar();}std::cout<<"\n""3) Custom deleter demo\n";std::ofstream("demo.txt")<<'x';// prepare the file to read{usingunique_file_t=std::unique_ptr<std::FILE,decltype(&close_file)>;unique_file_tfp(std::fopen("demo.txt","r"),&close_file);if(fp)std::cout<<char(std::fgetc(fp.get()))<<'\n';}// “close_file()” called here (if “fp” is not null)std::cout<<"\n""4) Custom lambda expression deleter and exception safety demo\n";try{std::unique_ptr<D,void(*)(D*)>p(newD,[](D*ptr){std::cout<<"destroying from a custom deleter...\n";deleteptr;});throwstd::runtime_error("");// “p” would leak here if it were a plain pointer}catch(conststd::exception&){std::cout<<"Caught exception\n";}std::cout<<"\n""5) Array form of unique_ptr demo\n";{std::unique_ptr<D[]>p(newD[3]);}// “D::~D()” is called 3 timesstd::cout<<"\n""6) Linked list demo\n";{Listwall;constintenough{1'000'000};for(intbeer=0;beer!=enough;++beer)wall.push(beer);std::cout.imbue(std::locale("en_US.UTF-8"));std::cout<<enough<<" bottles of beer on the wall...\n";}// destroys all the beers}Possible output:

1) Unique ownership semantics demo D::D D::bar D::~D 2) Runtime polymorphism demo D::D D::bar D::~D 3) Custom deleter demo x 4) Custom lambda-expression deleter and exception safety demo D::D destroying from a custom deleter... D::~D Caught exception 5) Array form of unique_ptr demo D::D D::D D::D D::~D D::~D D::~D 6) Linked list demo 1,000,000 bottles of beer on the wall... Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior

LWG 4144

C++11 T* was not required to form a valid type required See also