|
|
Member functions | ||||
Modifiers | ||||
Observers | ||||
Non-member functions | ||||
(C++14)(C++20) | ||||
(until C++20)(C++20) | ||||
(C++20) | ||||
Helper classes | ||||
Defined in header <memory> | ||
template< class T, | (1) | (since C++11) |
template< class T, | (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 theunique_ptr
goes out of scope.
The object is disposed of, using the associated deleter, when either of the following happens:
unique_ptr
object is destroyed.unique_ptr
object is assigned another pointer viaoperator= orreset().The object is disposed of, using a potentially user-supplied deleter, by callingget_deleter()(ptr). The default deleter (std::default_delete
) uses thedelete operator, which destroys the object and deallocates the memory.
Aunique_ptr
may alternatively own no object, in which case it is described asempty.
There are two versions ofunique_ptr
:
The class satisfies the requirements ofMoveConstructible andMoveAssignable, but of neitherCopyConstructible norCopyAssignable.
IfT*
was not a valid type (e.g.,T
is a reference type), a program that instantiates the definition ofstd::unique_ptr<T, Deleter> is ill-formed.
Type requirements | ||
-Deleter must beFunctionObject or lvalue reference to aFunctionObject or lvalue reference to function, callable with an argument of typeunique_ptr<T, Deleter>::pointer. |
Contents |
Only non-constunique_ptr
can transfer the ownership of the managed object to anotherunique_ptr
. If an object's lifetime is managed by aconst std::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:
unique_ptr
may be constructed for anincomplete typeT
, such as to facilitate the use as a handle in thepImpl 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, andreset
member function ofunique_ptr
. (In contrast,std::shared_ptr cannot be constructed from a raw pointer to incomplete type, but can be destroyed whereT
is incomplete). Note that ifT
is a class template specialization, use ofunique_ptr
as an operand, e.g.!p requiresT
's parameters to be complete due toADL.
IfT
is aderived class of some baseB
, thenunique_ptr<T> isimplicitly convertible tounique_ptr<B>. The default deleter of the resultingunique_ptr<B> will useoperator delete forB
, leading toundefined behavior unless the destructor ofB
isvirtual. Note thatstd::shared_ptr behaves differently:std::shared_ptr<B> will use theoperator delete for the typeT
and the owned object will be deleted correctly even if the destructor ofB
is notvirtual.
Unlikestd::shared_ptr,unique_ptr
may manage an object through any custom handle type that satisfiesNullablePointer. This allows, for example, managing objects located in shared memory, by supplying aDeleter
that definestypedefboost::offset_ptr pointer;
or anotherfancy pointer.
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_constexpr_memory | 202202L | (C++23) | constexprstd::unique_ptr |
Type | Definition |
pointer | std::remove_reference<Deleter>::type::pointer if that type exists, otherwiseT* . Must satisfyNullablePointer |
element_type | T , the type of the object managed by thisunique_ptr |
deleter_type | Deleter , the function object or lvalue reference to function or to function object, to be called from the destructor |
constructs a newunique_ptr (public member function)[edit] | |
destructs the managed object if such is present (public member function)[edit] | |
assigns theunique_ptr (public member function)[edit] | |
Modifiers | |
returns a pointer to the managed object and releases the ownership (public member function)[edit] | |
replaces the managed object (public member function)[edit] | |
swaps the managed objects (public member function)[edit] | |
Observers | |
returns a pointer to the managed object (public member function)[edit] | |
returns the deleter that is used for destruction of the managed object (public member function)[edit] | |
checks if there is an associated managed object (public member function)[edit] | |
Single-object version, | |
dereferences pointer to the managed object (public member function)[edit] | |
Array version, | |
provides indexed access to the managed array (public member function)[edit] |
(C++14)(C++20) | creates a unique pointer that manages a new object (function template)[edit] |
(removed in C++20)(C++20) | compares to anotherunique_ptr or withnullptr(function template)[edit] |
(C++20) | outputs the value of the managed pointer to an output stream (function template)[edit] |
(C++11) | specializes thestd::swap algorithm (function template)[edit] |
(C++11) | hash support forstd::unique_ptr (class template specialization)[edit] |
#include <cassert>#include <cstdio>#include <fstream>#include <iostream>#include <locale>#include <memory>#include <stdexcept> // helper class for runtime polymorphism demo belowstruct B{virtual ~B()=default; virtualvoid bar(){std::cout<<"B::bar\n";}}; struct D: B{ D(){std::cout<<"D::D\n";} ~D(){std::cout<<"D::~D\n";} void bar() 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();return p;} // helper function for the custom deleter demo belowvoid close_file(std::FILE* fp){std::fclose(fp);} // unique_ptr-based linked list demostruct List{struct Node{int data; 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){auto next= std::move(head->next); head= std::move(next);}} void push(int data){ head= std::unique_ptr<Node>(new Node{data, std::move(head)});}}; int main(){std::cout<<"1) Unique ownership semantics demo\n";{// Create a (uniquely owned) resource std::unique_ptr<D> p=std::make_unique<D>(); // Transfer ownership to “pass_through”,// which in turn transfers ownership back through the return value std::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 type std::unique_ptr<B> p=std::make_unique<D>(); // Dynamic dispatch works as expected p->bar();} std::cout<<"\n""3) Custom deleter demo\n";std::ofstream("demo.txt")<<'x';// prepare the file to read{using unique_file_t= std::unique_ptr<std::FILE, decltype(&close_file)>; unique_file_t fp(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(new D,[](D* ptr){std::cout<<"destroying from a custom deleter...\n"; delete ptr;}); 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(new D[3]);}// “D::~D()” is called 3 times std::cout<<"\n""6) Linked list demo\n";{ List wall;constint enough{1'000'000};for(int beer=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 demoD::DD::barD::~D 2) Runtime polymorphism demoD::DD::barD::~D 3) Custom deleter demox 4) Custom lambda-expression deleter and exception safety demoD::Ddestroying from a custom deleter...D::~DCaught exception 5) Array form of unique_ptr demoD::DD::DD::DD::~DD::~DD::~D 6) Linked list demo1,000,000 bottles of beer on the wall...
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 |
(C++11) | smart pointer with shared object ownership semantics (class template)[edit] |
(C++11) | weak reference to an object managed bystd::shared_ptr (class template)[edit] |
(C++26) | a wrapper containing dynamically-allocated object with value-like semantics (class template)[edit] |
(C++17) | objects that hold instances of anyCopyConstructible type (class)[edit] |