std::shared_ptr::reset(3)

NAME
std::shared_ptr::reset - std::shared_ptr::reset

Synopsis
   void reset() noexcept; (1) (since C++11)
   template< class Y > (2) (since C++11)
   void reset( Y* ptr );
   template< class Y, class Deleter > (3) (since C++11)
   void reset( Y* ptr, Deleter d );
   template< class Y, class Deleter, class Alloc > (4) (since C++11)
   void reset( Y* ptr, Deleter d, Alloc alloc );
   Replaces the managed object with an object pointed to by ptr. Optional deleter d can
   be supplied, which is later used to destroy the new object when no shared_ptr
   objects own it. By default, delete expression is used as deleter. Proper delete
   expression corresponding to the supplied type is always selected, this is the reason
   why the function is implemented as template using a separate parameter Y.
   If *this already owns an object and it is the last shared_ptr owning it, the object
   is destroyed through the owned deleter.
   If the object pointed to by ptr is already owned, the function generally results in
   undefined behavior.
   1) Releases the ownership of the managed object, if any. After the call, *this
   manages no object. Equivalent to shared_ptr().swap(*this);.
   2-4) Replaces the managed object with an object pointed to by ptr. Y must be a
   complete type and implicitly convertible to T. Additionally:
   2) Uses the delete expression as the deleter. A valid delete expression must be
   available, i.e. delete ptr must be well formed, have well-defined behavior and not
   throw any exceptions. Equivalent to shared_ptr<T>(ptr).swap(*this);.
   3) Uses the specified deleter d as the deleter. Deleter must be callable for the
   type T, i.e. d(ptr) must be well formed, have well-defined behavior and not throw
   any exceptions. Deleter must be CopyConstructible, and its copy constructor and
   destructor must not throw exceptions. Equivalent to shared_ptr<T>(ptr,
   d).swap(*this);.
   4) Same as (3), but additionally uses a copy of alloc for allocation of data for
   internal use. Alloc must be an Allocator. The copy constructor and destructor must
   not throw exceptions. Equivalent to shared_ptr<T>(ptr, d, alloc).swap(*this);.

Parameters
   ptr - pointer to an object to acquire ownership of
   d - deleter to store for deletion of the object
   alloc - allocator to use for internal allocations

Return value
   (none)

Exceptions
   2) std::bad_alloc if required additional memory could not be obtained. May throw
   implementation-defined exception for other errors. delete ptr is called if an
   exception occurs.
   3,4) std::bad_alloc if required additional memory could not be obtained. May throw
   implementation-defined exception for other errors. d(ptr) is called if an exception
   occurs.

Example
// Run this code
 #include <iostream>
 #include <memory>
 struct Foo
 {
     Foo(int n = 0) noexcept : bar(n)
     {
         std::cout << "Foo::Foo(), bar = " << bar << " @ " << this << '\n';
     }
     ~Foo()
     {
         std::cout << "Foo::~Foo(), bar = " << bar << " @ " << this << '\n';
     }
     int getBar() const noexcept { return bar; }
 private:
     int bar;
 };
 int main()
 {
     std::cout << "1) unique ownership\n";
     {
         std::shared_ptr<Foo> sptr = std::make_shared<Foo>(100);
         std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "
                   << sptr.use_count() << '\n';
         // Reset the shared_ptr without handing it a fresh instance of Foo.
         // The old instance will be destroyed after this call.
         std::cout << "call sptr.reset()...\n";
         sptr.reset(); // calls Foo's destructor here
         std::cout << "After reset(): use_count() = " << sptr.use_count()
                   << ", sptr = " << sptr << '\n';
     } // No call to Foo's destructor, it was done earlier in reset().
     std::cout << "\n2) unique ownership\n";
     {
         std::shared_ptr<Foo> sptr = std::make_shared<Foo>(200);
         std::cout << "Foo::bar = " << sptr->getBar() << ", use_count() = "
                   << sptr.use_count() << '\n';
         // Reset the shared_ptr, hand it a fresh instance of Foo.
         // The old instance will be destroyed after this call.
         std::cout << "call sptr.reset()...\n";
         sptr.reset(new Foo{222});
         std::cout << "After reset(): use_count() = " << sptr.use_count()
                   << ", sptr = " << sptr << "\nLeaving the scope...\n";
     } // Calls Foo's destructor.
     std::cout << "\n3) multiple ownership\n";
     {
         std::shared_ptr<Foo> sptr1 = std::make_shared<Foo>(300);
         std::shared_ptr<Foo> sptr2 = sptr1;
         std::shared_ptr<Foo> sptr3 = sptr2;
         std::cout << "Foo::bar = " << sptr1->getBar() << ", use_count() = "
                   << sptr1.use_count() << '\n';
         // Reset the shared_ptr sptr1, hand it a fresh instance of Foo.
         // The old instance will stay shared between sptr2 and sptr3.
         std::cout << "call sptr1.reset()...\n";
         sptr1.reset(new Foo{333});
         std::cout << "After reset():\n"
                   << "sptr1.use_count() = " << sptr1.use_count()
                   << ", sptr1 @ " << sptr1 << '\n'
                   << "sptr2.use_count() = " << sptr2.use_count()
                   << ", sptr2 @ " << sptr2 << '\n'
                   << "sptr3.use_count() = " << sptr3.use_count()
                   << ", sptr3 @ " << sptr3 << '\n'
                   << "Leaving the scope...\n";
     } // Calls two destructors of: 1) Foo owned by sptr1,
         // 2) Foo shared between sptr2/sptr3.
 }

Possible output:
 1) unique ownership
 Foo::Foo(), bar = 100 @ 0x23c5040
 Foo::bar = 100, use_count() = 1
 call sptr.reset()...
 Foo::~Foo(), bar = 100 @ 0x23c5040
 After reset(): use_count() = 0, sptr = 0
 2) unique ownership
 Foo::Foo(), bar = 200 @ 0x23c5040
 Foo::bar = 200, use_count() = 1
 call sptr.reset()...
 Foo::Foo(), bar = 222 @ 0x23c5050
 Foo::~Foo(), bar = 200 @ 0x23c5040
 After reset(): use_count() = 1, sptr = 0x23c5050
 Leaving the scope...
 Foo::~Foo(), bar = 222 @ 0x23c5050
 3) multiple ownership
 Foo::Foo(), bar = 300 @ 0x23c5080
 Foo::bar = 300, use_count() = 3
 call sptr1.reset()...
 Foo::Foo(), bar = 333 @ 0x23c5050
 After reset():
 sptr1.use_count() = 1, sptr1 @ 0x23c5050
 sptr2.use_count() = 2, sptr2 @ 0x23c5080
 sptr3.use_count() = 2, sptr3 @ 0x23c5080
 Leaving the scope...
 Foo::~Foo(), bar = 300 @ 0x23c5080
 Foo::~Foo(), bar = 333 @ 0x23c5050

See also
   constructor constructs new shared_ptr
                 (public member function)