Namespaces
Variants
Actions

std::unique_ptr

From cppreference.com
< cpp‎ | memory
 
 
Memory management library
(exposition only*)
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage(until C++20)
(until C++20*)
(until C++20*)
Garbage collector support(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
 
 
Defined in header <memory>
template<

    class T,
    class Deleter =std::default_delete<T>

>class unique_ptr;
(1) (since C++11)
template<

    class T,
    class Deleter

>class unique_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:

  1. Manages a single object (e.g., allocated with new).
  2. 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.

Contents

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

  • 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 typeT, 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_memory202202L(C++23)constexprstd::unique_ptr

[edit]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_ptr
deleter_typeDeleter, the function object or lvalue reference to function or to function object, to be called from the destructor

[edit]Member functions

constructs a new unique_ptr
(public member function)[edit]
destructs the managed object if such is present
(public member function)[edit]
assigns the unique_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, unique_ptr<T>
dereferences pointer to the managed object
(public member function)[edit]
Array version, unique_ptr<T[]>
provides indexed access to the managed array
(public member function)[edit]

[edit]Non-member functions

creates a unique pointer that manages a new object
(function template)[edit]
compares to another unique_ptr or with nullptr
(function template)[edit]
outputs the value of the managed pointer to an output stream
(function template)[edit]
specializes the std::swap algorithm
(function template)[edit]

[edit]Helper classes

hash support for std::unique_ptr
(class template specialization)[edit]

[edit]Example

#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 reference std::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 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...

[edit]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 4144C++11 T* was not required to form a valid type required

[edit]See also

(C++11)
smart pointer with shared object ownership semantics
(class template)[edit]
(C++11)
weak reference to an object managed by std::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 any CopyConstructible type
(class)[edit]
close