Namespaces
Variants

std::unique_ptr<T,Deleter>:: unique_ptr

From cppreference.net
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* )
( 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)
miembros de la plantilla principal, unique_ptr<T>
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
explicit unique_ptr ( pointer p ) noexcept ;
(2) (constexpr desde C++23)
unique_ptr ( pointer p, /* ver más abajo */ d1 ) noexcept ;
(3) (constexpr desde C++23)
unique_ptr ( pointer p, /* ver más abajo */ d2 ) noexcept ;
(4) (constexpr desde C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr desde C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr desde C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
template < class U >
unique_ptr ( std:: auto_ptr < U > && u ) noexcept ;
(8) (eliminado en C++17)
miembros de la especialización para arrays, unique_ptr<T[]>
constexpr unique_ptr ( ) noexcept ;
constexpr unique_ptr ( std:: nullptr_t ) noexcept ;
(1)
template < class U >
explicit unique_ptr ( U p ) noexcept ;
(2) (constexpr desde C++23)
template < class U >
unique_ptr ( U p, /* ver más abajo */ d1 ) noexcept ;
(3) (constexpr desde C++23)
template < class U >
unique_ptr ( U p, /* ver más abajo */ d2 ) noexcept ;
(4) (constexpr desde C++23)
unique_ptr ( unique_ptr && u ) noexcept ;
(5) (constexpr desde C++23)
template < class U, class E >
unique_ptr ( unique_ptr < U, E > && u ) noexcept ;
(6) (constexpr desde C++23)
unique_ptr ( const unique_ptr & ) = delete ;
(7)
1) Construye un std::unique_ptr que no posee nada. Inicializa por valor el puntero almacenado y el eliminador almacenado. Requiere que Deleter sea DefaultConstructible y que la construcción no lance una excepción. Estas sobrecargas participan en la resolución de sobrecarga solo si std:: is_default_constructible < Deleter > :: value es true y Deleter no es un tipo puntero.
2) Construye un std::unique_ptr que posee p , inicializando el puntero almacenado con p e inicializando por valor el eliminador almacenado. Requiere que Deleter sea DefaultConstructible y que la construcción no lance una excepción. Esta sobrecarga participa en la resolución de sobrecarga solo si std:: is_default_constructible < Deleter > :: value es true y Deleter no es un tipo puntero.

Este constructor no es seleccionado por deducción de argumentos de plantilla de clase .

(desde C++17)
3,4) Construye un objeto std::unique_ptr que posee p , inicializando el puntero almacenado con p e inicializando un deleter D como se indica a continuación (depende de si D es un tipo de referencia).
a) Si D es un tipo no-referencia A , entonces las firmas son:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1) (requiere que Deleter sea nothrow- CopyConstructible )
unique_ptr ( pointer p, A && d ) noexcept ;
(2) (requiere que Deleter sea nothrow- MoveConstructible )
b) Si D es un tipo de referencia lvalue A & , entonces las firmas son:
unique_ptr ( pointer p, A & d ) noexcept ;
(1)
unique_ptr ( pointer p, A && d ) = delete ;
(2)
c) Si D es un tipo de referencia lvalue const A & , entonces las firmas son:
unique_ptr ( pointer p, const A & d ) noexcept ;
(1)
unique_ptr ( pointer p, const A && d ) = delete ;
(2)
En todos los casos, el deleter se inicializa desde std:: forward < decltype ( d ) > ( d ) . Estas sobrecargas participan en la resolución de sobrecarga solo si std:: is_constructible < D, decltype ( d ) > :: value es true .

Estos dos constructores no son seleccionados por class template argument deduction .

(since C++17)
2-4) En la especialización para arreglos se comportan igual que los constructores que toman un parámetro de puntero en la plantilla principal, excepto que adicionalmente no participan en la resolución de sobrecarga a menos que una de las siguientes condiciones sea verdadera:
  • U es el mismo tipo que pointer , o
  • U es std::nullptr_t , o
  • pointer es el mismo tipo que element_type* y U es algún tipo de puntero V* tal que V(*)[] es implícitamente convertible a element_type(*)[] .
5) Construye un unique_ptr transfiriendo la propiedad desde u a * this y almacena el puntero nulo en u . Este constructor solo participa en la resolución de sobrecarga si std:: is_move_constructible < Deleter > :: value es true . Si Deleter no es un tipo referencia, requiere que sea nothrow- MoveConstructible (si Deleter es una referencia, get_deleter() y u.get_deleter() después de la construcción por movimiento referencian el mismo valor).
6) Construye un unique_ptr transfiriendo la propiedad desde u hacia * this , donde u está construido con un eliminador especificado ( E ). Depende de si E es un tipo de referencia, como sigue:
a) si E es un tipo de referencia, este deleter se construye por copia desde u 's deleter (requiere que esta construcción no lance excepciones),
b) si E es un tipo no-referencia, este deleter se construye por movimiento desde u 's deleter (requiere que esta construcción no lance excepciones).
Este constructor solo participa en la resolución de sobrecarga si se cumple todo lo siguiente:
a) unique_ptr < U, E > :: pointer es implícitamente convertible a pointer ,
b) U no es un tipo de array,
c) ya sea que Deleter sea un tipo de referencia y E sea del mismo tipo que Deleter , o que Deleter no sea un tipo de referencia y E sea convertible implícitamente a Deleter .
6) En la especialización para arreglos se comporta igual que en la plantilla principal, excepto que solo participará en la resolución de sobrecarga si se cumple todo lo siguiente:
  • U es un tipo de arreglo,
  • pointer es del mismo tipo que element_type* ,
  • unique_ptr < U,E > :: pointer es del mismo tipo que unique_ptr < U,E > :: element_type * ,
  • unique_ptr < U,E > :: element_type ( * ) [ ] es convertible a element_type(*)[] ,
  • ya sea que Deleter sea un tipo de referencia y E sea del mismo tipo que Deleter , o que Deleter no sea un tipo de referencia y E sea implícitamente convertible a Deleter .
7) El constructor de copia está explícitamente eliminado.
8) Construye un unique_ptr donde el puntero almacenado se inicializa con u.release() y el deleter almacenado se inicializa por valor. Este constructor solo participa en la resolución de sobrecarga si U* es convertible implícitamente a T* y Deleter es del mismo tipo que std:: default_delete < T > .

Contenidos

Parámetros

p - un puntero a un objeto para gestionar
d1, d2 - un deleter para usar para destruir el objeto
u - otro smart pointer del cual adquirir la propiedad

Notas

En lugar de usar la sobrecarga (2) junto con new, a menudo es mejor idea usar std::make_unique<T> .

(since C++14)

std:: unique_ptr < Derived > es implícitamente convertible a std:: unique_ptr < Base > mediante la sobrecarga (6) (ya que tanto el puntero gestionado como std::default_delete son implícitamente convertibles).

Debido a que el constructor por defecto es constexpr , los unique_ptrs estáticos se inicializan como parte de la inicialización no-local estática , antes de que comience cualquier inicialización no-local dinámica. Esto hace seguro usar un unique_ptr en el constructor de cualquier objeto estático.

No existe deducción de argumentos de plantilla de clase a partir de tipos puntero porque es imposible distinguir entre un puntero obtenido de las formas con array y sin array de new .

(desde C++17)

Ejemplo

#include <iostream>
#include <memory>
struct Foo // objeto a gestionar
{
    Foo() { std::cout << "Foo ctor\n"; }
    Foo(const Foo&) { std::cout << "Foo copy ctor\n"; }
    Foo(Foo&&) { std::cout << "Foo move ctor\n"; }
    ~Foo() { std::cout << "~Foo dtor\n"; }
};
struct D // deleter
{
    D() {};
    D(const D&) { std::cout << "Constructor de copia D\n"; }
    D(D&) { std::cout << "D constructor de copia no constante\n"; }
    D(D&&) { std::cout << "D move ctor \n"; }
    void operator()(Foo* p) const
    {
        std::cout << "D está eliminando un Foo\n";
        delete p;
    };
};
int main()
{
    std::cout << "Ejemplo de constructor(1)...\n";
    std::unique_ptr<Foo> up1; // up1 está vacío
    std::unique_ptr<Foo> up1b(nullptr); // up1b está vacío
    std::cout << "Ejemplo constructor(2)...\n";
    {
        std::unique_ptr<Foo> up2(new Foo); //up2 ahora posee un Foo
    } // Foo eliminado
    std::cout << "Ejemplo constructor(3)...\n";
    D d;
    {   // el tipo deleter no es una referencia
        std::unique_ptr<Foo, D> up3(new Foo, d); // deleter copiado
    }
    {   // el tipo deleter es una referencia
        std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b contiene una referencia a d
    }
    std::cout << "Ejemplo constructor(4)...\n";
    {   // deleter no es una referencia
        std::unique_ptr<Foo, D> up4(new Foo, D()); // deleter moved
    }
    std::cout << "Ejemplo constructor(5)...\n";
    {
        std::unique_ptr<Foo> up5a(new Foo);
        std::unique_ptr<Foo> up5b(std::mover(up5a)); // transferencia de propiedad
    }
    std::cout << "Ejemplo constructor(6)...\n";
    {
        std::unique_ptr<Foo, D> up6a(new Foo, d); // D se copia
        std::unique_ptr<Foo, D> up6b(std::move(up6a)); // D se ha movido
        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D es una referencia
        std::unique_ptr<Foo, D> up6d(std::mover(up6c)); // D se copia
    }
#if (__cplusplus < 201703L)
    std::cout << "Ejemplo constructor(7)...\n";
    {
        std::auto_ptr<Foo> up7a(new Foo);
        std::unique_ptr<Foo> up7b(std::mover(up7a)); // transferencia de propiedad
    }
#endif
    std::cout << "Constructor de array de ejemplo...\n";
    {
        std::unique_ptr<Foo[]> up(new Foo[3]);
    } // tres objetos Foo eliminados
}

Salida:

Ejemplo constructor(1)...
Ejemplo constructor(2)...
Foo ctor
~Foo dtor
Ejemplo constructor(3)...
Foo ctor
D copy ctor
D is deleting a Foo
~Foo dtor
Foo ctor
D is deleting a Foo
~Foo dtor
Ejemplo constructor(4)...
Foo ctor
D move ctor
D is deleting a Foo
~Foo dtor
Ejemplo constructor(5)...
Foo ctor
~Foo dtor
Ejemplo constructor(6)...
Foo ctor
D copy ctor
D move ctor
Foo ctor
D non-const copy ctor
D is deleting a Foo
~Foo dtor
D is deleting a Foo
~Foo dtor
Ejemplo constructor(7)...
Foo ctor
~Foo dtor
Ejemplo array constructor...
Foo ctor
Foo ctor
Foo ctor
~Foo dtor
~Foo dtor
~Foo dtor

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 2118 C++11 Los constructores de unique_ptr<T[]> rechazaban conversiones de calificación. Aceptar.
LWG 2520 C++11 unique_ptr<T[]> se hizo accidentalmente no construible desde nullptr_t . Hacerlo construible.
LWG 2801 C++11 El constructor por defecto no estaba restringido. Restringido.
LWG 2899 C++11 El constructor de movimiento no estaba restringido. Restringido.
LWG 2905 C++11 La restricción en el constructor desde un puntero y un deleter era incorrecta. Corregido.
LWG 2944 C++11 Algunas precondiciones fueron eliminadas accidentalmente por LWG 2905 Restauradas.