Defined in header
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
or
.
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
and
, but of neither
nor
.
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
or lvalue reference to a
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
, which hold pointers to dynamically-allocated objects (e.g. if polymorphic behavior is desired).
unique_ptr may be constructed for an
T, such as to facilitate the use as a handle in the
. 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,
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
.
If T is a
of some base B, then unique_ptr<T> is
to unique_ptr<B>. The default deleter of the resulting unique_ptr<B> will use
for B, leading to
unless the destructor of B is
. Note that
behaves differently: std::shared_ptr<B> will use the
for the type T and the owned object will be deleted correctly even if the destructor of B is not
.
Unlike
, unique_ptr may manage an object through any custom handle type that satisfies
. This allows, for example, managing objects located in shared memory, by supplying a Deleter that defines typedef
pointer; or another
.
macroValueStdFeature
(C++23)constexpr
Nested types
Type Definition pointerstd::remove_reference<Deleter>::type::pointer if that type exists, otherwise T*. Must satisfy
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
constructs a new unique_ptr
(public member function)
destructs the managed object if such is present
(public member function)
assigns the unique_ptr
(public member function)
Modifiers
returns a pointer to the managed object and releases the ownership
(public member function)
replaces the managed object
(public member function)
swaps the managed objects
(public member function)
Observers
returns a pointer to the managed object
(public member function)
returns the deleter that is used for destruction of the managed object
(public member function)
checks if there is an associated managed object
(public member function)
Single-object version, unique_ptr<T>
dereferences pointer to the managed object
(public member function)
Array version, unique_ptr<T[]>
provides indexed access to the managed array
(public member function)
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
C++11 T* was not required to form a valid type required See also