Składnia
#include <memory>
namespace std
{
    template < class T, class...Args >
    unique_ptr < T > make_unique( Args &&...args );
    
    template < class T >
    std::unique_ptr < T[] > make_unique( std::size_t size );
    
    template < class T, class...Args >
     make_unique( Args &&...args ) = delete;
}
Parametry szablonu
Argumenty
Zwracana wartość
Zależnie od wersji użytej funkcji dla typu T: 
std::unique_ptr < T >
 lub 
std::unique_ptr < T[] >
.
Opis szczegółowy
Funkcja zwraca inteligentny wskaźnik 
std::unique_ptr < T >
 przekazując podane argumenty do konstruktora typu T. Możemy zaalokować pojedyńczy obiekt typu T, lub dynamiczną tablicę obiektów typu T.
Wg 
Scotta Meyersa z książki "Skuteczny nowoczesny C++" funkcja 
std::make_unique()
 powinna być stosowana zamiast ręcznego tworzenia 
std::unique_ptr <>
 i allokacji za pomocą 
operator new
 z dwóch powodów:
1. Krótszego zapisu, mniejszej podatności na błędy modyfikacji kodu, mniejszej duplikacji kodu:
std::unique_ptr < std::string > text( new std::string );
auto text = std::make_unique < std::string >();
2. Większego bezpieczeństwa wątkowego.
Mając funkcję np.: 
void saveText( std::unique_ptr < std::string > text, int textDepth );
 i wywułując np.: 
saveText( new std::string( "Ala ma świnkę morską" ), computeDepthLevelFromEnvironment() );
 oraz wiedząc, że nie jest zdefiniowana kolejność ewaluacji argumentów funkcji może się zdarzyć sytuacja, że wpierw zaalokujemy obiekt, następnie funkcja computeDepthLevelFromEnvironment() wyrzuci wyjątek -wtedy nastąpi wyciek pamięci. W podobnej sytuacji stosując 
std::make_unique
 destruktor obiektu 
std::unique_ptr
 posprząta zaalokowaną pamięć.
Dodatkowe informacje
W razie konieczności podania własnego deletera funkcja 
std::make_unique()
 tego nie obsługuje, dlatego wtedy musimy utworzyć inteligentny wskaźnik bez użycia funkcji, przykładowo:
#include <iostream>
#include <string>
#include <memory>
int main()
{
    auto printingStringDeleter =[]( std::string * text )
    {
        std::cout << "Deleting: '" << * text << "'\n";
        delete text;
    };
    
    std::unique_ptr < std::string, decltype( printingStringDeleter ) > dummyText( new std::string( "Ala ma kota" ), printingStringDeleter );
}
Standardowe wyjście programu:
Deleting: 'Ala ma kota'
Kolejną sytuacją kiedy funkcja sprawia problemy jest używanie inicjatorów klamrowych (inicjatory klamrowe nie mogą być przekazywane doskonale):
#include <iostream>
#include <vector>
#include <memory>  
#include <iterator>  
#include <algorithm>  
int main()
{
    
    
    
    
    auto valuesToInitialise = { 1, 3, 5 };
    auto vectorPtr = std::make_unique < std::vector < int >>( valuesToInitialise );
    std::cout << "\nvector.size() = " << vectorPtr->size() << ", elements: ";
    std::copy( vectorPtr->cbegin(), vectorPtr->cend(), std::ostream_iterator < int >( std::cout, ", " ) );
    
    std::cout << std::endl;
}
Standardowe wyjście programu:
vector.size() = 3, elements: 1, 3, 5,
Rzucane wyjątki
Funkcja może wyrzucić te same wyjątki, które może wyrzucić konstruktor obiektu typu T. Może również być wyrzucony 
std::bad_alloc
 w razie braku pamięci.
Wymagania
Kompilator zgodny przynajmniej z C++14 powinien dostarczyć funkcję 
std::make_unique()
.
Jeśli nasz kompilator jej nie posiada, a posiada 
std::unique_ptr <>
 możemy użyć przykładowej implementacji z tego artykułu. W ostateczności możemy użyć inteligętnego wskaźnika z biblioteki boost:  
boost::make_unique.
Implementacja
Zaczerpnięta z 
En.cppreference.com:
template < typename T, typename...Arg >
std::unique_ptr < T > make_unique( Arg &&...args )
{
    return std::unique_ptr < T >( new T( std::forward < Arg >( args )...) );
}
Przykład
#include <iostream>
#include <vector>
#include <memory>  
#include <iterator>  
#include <algorithm>  
int main()
{
    auto vectorPtr = std::make_unique < std::vector < int >>();
    std::cout << "vector.size() = " << vectorPtr->size() << ", elements: ";
    std::copy( vectorPtr->cbegin(), vectorPtr->cend(), std::ostream_iterator < int >( std::cout, ", " ) );
    
    vectorPtr = std::make_unique < std::vector < int >>( 2, 3 );
    std::cout << "\nvector.size() = " << vectorPtr->size() << ", elements: ";
    std::copy( vectorPtr->cbegin(), vectorPtr->cend(), std::ostream_iterator < int >( std::cout, ", " ) );
    
    std::cout << std::endl;
}
Standardowe wyjście programu:
vector.size() = 0, elements: 
vector.size() = 2, elements: 3, 3, 
Zagadnienia powiązane
| auto_ptr | Przechowuje wskaźnik na zaalokowany obiekt zapewniając jednocześnie jego zwolnienie z chwilą wywołania destruktora. (szablon klasy) | 
|---|
| shared_ptr | Przechowuje wskaźnik i kontroluje liczbę istniejących kopii wskaźnika (automatycznie zwalnia pamięć). (szablon klasy) | 
|---|
| scoped_ptr | Automatycznie zwalnia pamięć zaalokowaną przy pomocy operatora newprzy wyjściu ze scope-a. (szablon klasy) | 
|---|
Linki zewnętrzne
Linki zewnętrzne