// C++11



std::auto_ptr   depricated in C++11
=============


#include <memory>

template< class T > class auto_ptr;
template<> class auto_ptr<void>   // no member functions


auto_ptr should not be used in new code. Use unique_ptr instead.




std::unique_ptr   since C++11
===============


#include <memory>

template< class T, class Deleter = std::default_delete<T>> class unique_ptr;
template <class T, class Deleter> class unique_ptr<T[],Deleter>;



Moveable (MoveConstructible and MoveAssignable) but not copyable or assignable:



void f()
{
    std::unique_ptr<Foo> up(new Foo());  // up is the only owner
    std::unique_ptr<Foo> up2(up);    // syntax error: can't copy unique_ptr

    std::unique_ptr<Foo> up3;        // nullptr: not owner

    up3 = up;                   // syntax error: can't assign unique_ptr
    up3 = std::move(up);        // ownership moved to up3  

} // up3 destroyed: Foo object is destructed
  // up  destroyed: nop




Not to accept raw pointers in assignment:


Foo *fooPtr = ... ;
std::unique_ptr<Foo> up(new Foo());

up = fooPtr; // syntax error!!!




Convertable to boolean:


void f()
{
    std::unique_ptr<Foo> up(new Foo());  // up is the only owner

    if ( up )  // owner or not
    {
        *up;   // use the object
    }
}




Convertible to shared_ptr:


std::unique_ptr<Foo> up(new Foo());
std::shared_ptr<Foo> sp = up;



Use make_unique<>   since C++14



std::unique_ptr<T> v1 = std::make_unique<T>();      // default constructor of T
std::unique_ptr<T> v2 = std::make_unique<T>(x,y,z); // constructor with params 
std::unique_ptr<T[]> v3 = std::make_unique<T[]>(5); // array of 5 elements








Source/sink:


void sink(std::unique_ptr<Foo> p)
{
    // destroyes Foo object
}

std::unique_ptr<Foo> source()
{
    // creates Foo object and moves back
    return std::unique_ptr<Foo>(new Foo);
}

void f()
{
    auto up = source();

    // use up

    sink(up);                    // syntax error: can't copy
    sink(move(up));              // ok: move

    return 0;
}



Will this work?:


unique_ptr<Foo> source()
{
    std::unique_ptr<Foo> up(new Foo);  // creates a Foo object

    return up;  // ????
}



Abstract factory pattern example (from Scott Meyers: Effective Modern C++)


class Base { ... };


class Derived1 : public Base { ... };

class Derived2 : public Base { ... };

class Derived3 : public Base { ... };




template <typename... Ts>
std::unique_ptr<Base>  makeBase( Ts&&... params)  { ... }



// client code:
void f()
{
    auto pBase = makeBase( /* arguments */ );


}	// destroy object



Custom deleter:


auto delBase = [](Base *pBase)
               {
                   makeLogEntry(pBase);
                   delete pBase;	// delete object
               };

template <typename... Ts>
std::unique_ptr<Base, decltype(delBase)>  makeBase( Ts&&... params)
{
    std::unique_ptr<Base, decltype(delBase)> pBase(nullptr, delBase);

    if ( /* Derived1 */ )
    {
        pBase.reset(new Derived1( std::forward<Ts>(params)...));
    }
    else if ( /* Derived2 */ )
    {
        pBase.reset(new Derived2( std::forward<Ts>(params)...));
    }
    else if ( /* Derived3 */ )
    {
        pBase.reset(new Derived3( std::forward<Ts>(params)...));
    }
    return pBase;
}



Size:

- The sizeof(unique_ptr<>) without deleter is == sizeof(raw pointer)
- If there is deleter with state, the size increases
- If no state, then no size penalty (e.g. lambda with no capture).
- If no state, but function pointer is used as deleter -> sizeof(funptr) added

State stored in deleter may increase the size of unique_ptr.



Unique_ptr has two forms:

  std::unique_ptr<T>
      has  operator* and operator->

  std::unique_ptr<T[]>
      has operator[]





How to emulate boost:scoped_ptr?:


void f()
{
    boost::scoped_ptr<Foo> sp(new Foo);
    std::unique_ptr<Foo>   up(new Foo);

    boost::scoped_ptr<Foo> sp2;
    std::unique_ptr<Foo>   up2;

    sp2 = sp;  // syntax error
    up2 = up;  // syntax error

    sp2 = std::move(sp);  // syntax error
    up2 = std::move(up);  // ok
}



void f()
{
    const std::unique_ptr<Foo> up(new Foo);

    std::unique_ptr<Foo>   up2;

    up2 = std::move(up);  // syntax error
}



The ugly swap:


void f()
{
    boost::scoped_ptr<Foo> sp1(new Foo);
    const std::unique_ptr<Foo> up1(new Foo);

    {
        boost::scoped_ptr<Foo> sp2(new Foo);
        const std::unique_ptr<Foo> up2(new Foo);

        swap(sp1,sp2);  // ok: swap works on scoped_ptr
	swap(up1,up2);  // syntax error: no move on const 
    }
}




Prefer unique_ptr over shared_ptr until you need more owner

 - replace auto_ptr when want to use a single ownership pointer
 - exception safety for dynamically allocated objects
 - using source/sink strategy for controlling object lifetime
 - use in standard containers when polymorphic usage is needed
 - it is cheap - only the pointer size


Not to use when:

 - need downcast (dynamic cast): No special cast operations are provided




std::shared::ptr    since C++11
================

#include <memory>

template< class T > class shared_ptr;




Shared ownership with copy semantics (copy constructible and copy assignable)



What about unique_array<> and shared_array<> ?


There is  aspecialization for unique_ptr<T[]>.

// from http://stackoverflow.com/questions/8624146/c11-standard-scoped-array-wrappers
#include <iostream>
#include <memory>

struct test
{
  ~test() { std::cout << "test::dtor" << std::endl; }
};

int main()
{
  std::unique_ptr<test[]> array(new test[3]);
}

When you run it, you will get this messages.

test::dtor
test::dtor
test::dtor


If you want to use shared_ptr, you should use std::default_delete<T[]>
for deleter since it doesn't have one like shared_ptr<t[]>.

std::shared_ptr<test> array(new test[3], std::default_delete<test[]>());


Issues
======


1. Smart opointers are not polymorphic - they only simalte that with op=, etc.

   - Kovariant return types do not work with smart pointers

2. You can still make memory leak - with circulat shared_ptr, etc.



Stroustrup
==========

  Owner pointers are better than smart pointers