home | help
std::unique_ptr(3)	       C++ Standard Libary	      std::unique_ptr(3)

NAME
     std::unique_ptr - std::unique_ptr

Synopsis
	Defined in header <memory>
	template<

	    class T,				   (1) (since C++11)
	    class Deleter = std::default_delete<T>

	> class unique_ptr;
	template <

	    class T,				   (2) (since C++11)
	    class Deleter

	> class unique_ptr<T[], Deleter>;

	std::unique_ptr  is a smart pointer that owns and manages another object
     through a
	pointer and 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 oper-
     ator= or
	    reset().

	The object is disposed of, using a potentially user-supplied deleter  by
     calling
	get_deleter()(ptr).  The default deleter 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 called
     empty.

	There are two versions of std::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 MoveAs-
     signable, but of
	neither CopyConstructible nor CopyAssignable.

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 ob-
     ject 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.

	std::unique_ptr  is commonly used to manage the lifetime of objects, in-
     cluding:

	  * providing exception safety to classes and functions that handle  ob-
     jects 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 be-
     havior is
	    desired).

	std::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  hap-
     pens in the
	destructor,  move  assignment  operator,  and  reset  member function of
     std::unique_ptr.
	(Conversely, std::shared_ptr can't 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  re-
     quires T's
	parameters to be complete due to ADL.

	If  T  is a derived class of some base B, then std::unique_ptr<T> is im-
     plicitly
	convertible to std::unique_ptr<B>. The default deleter of the resulting
	std::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, std::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 macro	    Value    Std	    Feature
	__cpp_lib_constexpr_memory 202202L (C++23) constexpr std::unique_ptr

Member types
	Member type  Definition
	pointer       std::remove_reference<Deleter>::type::pointer if that type
     exists,
		     otherwise T*. Must satisfy NullablePointer
	element_type T, the type of the object managed by this unique_ptr
	deleter_type Deleter, the function object or lvalue reference  to  func-
     tion or to
		     function object, to be called from the destructor

Member functions
	constructor   constructs a new unique_ptr
		      (public member function)
	destructor    destructs the managed object if such is present
		      (public member function)
	operator=     assigns the unique_ptr
		      (public member function)

Modifiers
	release        returns	a pointer to the managed object and releases the
     ownership
		      (public member function)
	reset	      replaces the managed object
		      (public member function)
	swap	      swaps the managed objects
		      (public member function)

Observers
	get	      returns a pointer to the managed object
		      (public member function)
	get_deleter   returns the deleter that is used for  destruction  of  the
     managed object
		      (public member function)
	operator bool checks if there is an associated managed object
		      (public member function)

Single-object version, unique_ptr<T>
	operator*     dereferences pointer to the managed object
	operator->    (public member function)

Array version, unique_ptr<T[]>
	operator[]    provides indexed access to the managed array
		      (public member function)

Non-member functions
	make_unique
	make_unique_for_overwrite    creates a unique pointer that manages a new
     object
	(C++14) 		    (function template)
	(C++20)
	operator==
	operator!=
	operator<
	operator<=		     compares  to  another  unique_ptr	or  with
     nullptr
	operator>		    (function template)
	operator>=
	operator<=>
	(removed in C++20)
	(C++20)
	operator<<(std::unique_ptr)  outputs the value of the managed pointer to
     an output
	(C++20) 		    stream
				    (function template)
	std::swap(std::unique_ptr)  specializes the std::swap algorithm
	(C++11) 		    (function template)

Helper classes
	std::hash<std::unique_ptr> hash support for std::unique_ptr
	(C++11) 		   (class template specialization)

Example
     // Run this code

      #include <cassert>
      #include <cstdio>
      #include <fstream>
      #include <iostream>
      #include <locale>
      #include <memory>
      #include <stdexcept>

      // helper class for runtime polymorphism demo below
      struct B
      {
	  virtual ~B() = default;

	  virtual void 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 below
      void close_file(std::FILE* fp)
      {
	  std::fclose(fp);
      }

      // unique_ptr-based linked list demo
      struct 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 destruc-
     tor
	      //  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 nullptr
	      assert(!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,     de-
     cltype(&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;
	      });

	      throw std::runtime_error(""); // `p` would leak here if it were  a
     plain pointer
	  }
	  catch (const std::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;
	      const int 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...

See also
	shared_ptr smart pointer with shared object ownership semantics
	(C++11)    (class template)
	weak_ptr   weak reference to an object managed by std::shared_ptr
	(C++11)    (class template)

http://cppreference.com 	   2024.06.10		      std::unique_ptr(3)

home | help