Espacios de nombres
Variantes

std::unique_ptr::unique_ptr

De cppreference.com
 
 
Biblioteca de servicios
 
Gestión de memoria dinámica
Punteros inteligentes
(C++11)
(C++11)
(C++11)
(hasta C++17)
(C++11)
(C++23)
Asignadores de memoria
Recursos de memoria
Almacenamiento no inicializado
Algoritmos de memoria no inicializada
Algoritmos restringidos de memoria no inicializada
Apoyo para recolección de basura
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
(C++11)(hasta C++23)
Misceláneos
(C++20)
(C++11)
(C++11)
 
 
<tbody> </tbody>
Miembros de la plantilla primaria, unique_ptr<T>
constexpr unique_ptr() noexcept; constexpr unique_ptr( std::nullptr_t ) noexcept;
(1)
explicit unique_ptr( pointer p ) noexcept;
(2) (constexpr since C++23)
unique_ptr( pointer p, /* véase a continuación */ d1 ) noexcept;
(3) (constexpr since C++23)
unique_ptr( pointer p, /* véase a continuación */ d2 ) noexcept;
(4) (constexpr since C++23)
unique_ptr( unique_ptr&& u ) noexcept;
(5) (constexpr since C++23)
template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ) noexcept;
(6) (constexpr since C++23)
template< class U > unique_ptr( std::auto_ptr<U>&& u ) noexcept;
(7) (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 since C++23)
template< class U > unique_ptr( U p, /* véase a continuación */ d1 ) noexcept;
(3) (constexpr since C++23)
template< class U > unique_ptr( U p, /* véase a continuación */ d2 ) noexcept;
(4) (constexpr since C++23)
unique_ptr( unique_ptr&& u ) noexcept;
(5) (constexpr since C++23)
template< class U, class E > unique_ptr( unique_ptr<U, E>&& u ) noexcept;
(6) (constexpr since C++23)
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 esa construcción no lance excepciones. Estas sobrecargas solo participan en la resolución de sobrecargas 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 esa construcción no lance excepciones. Esta sobrecarga solo participa en la resolución de sobrecargas si std::is_default_constructible<Deleter>::value es true y Deleter no es un tipo puntero.

Este constructor no se selecciona por la deducción de argumentos de plantillas de clase.

(desde C++17)
3-4) Construye un std::unique_ptr que posee p, inicializando el puntero almacenado con p e inicializando un eliminador D como se describe a continuación (depende de si D es un tipo referencia):
a) Si D no es un tipo referencia A, entonces las signaturas son: <tbody> </tbody>
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 referencia l-valor A&, entonces las signaturas son: <tbody> </tbody>
unique_ptr(pointer p, A& d) noexcept;
(1)
unique_ptr(pointer p, A&& d) = delete;
(2)
c) Si D es un tipo referencia l-valor const A&, entonces las signaturas son: <tbody> </tbody>
unique_ptr(pointer p, const A& d) noexcept;
(1)
unique_ptr(pointer p, const A&& d) = delete;
(2)
En todos los casos el eliminiador se inicializa a partir de std::forward<decltype(d)>(d). Estas sobrecargas solo participan en la resolución de sobrecargas si std::is_constructible<D, decltype(d)>::value es true.

Estos dos constructores no se seleccionan por la deducción de argumentos de plantillas de clase.

(desde C++17)
2-4) En la especialización para arrays se comporta igual que los constructores que toman un parámetro de puntero en la plantilla principal, excepto que, además, no participan en la resolución de sobrecarga a menos que se cumpla una de las siguientes condiciones:
  • 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 puntero V* tal que V(*)[] es convertible implícitamente a element_type(*)[].
5) Construye un std::unique_ptr transfiriendo la posesión de 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() referencian el mismo valor después de la construcción).
6) Construye un std::unique_ptr transfiriendo la posesión de u a *this, donde u se construye con un eliminador especificado (E). Depende de si E es un tipo referencia, de la siguiente manera:
a) Si E es un tipo referencia, este eliminador se construye por copia del eliminador de u (requiere que esta construcción no lance excepciones).
b) Si E no es un tipo referencia, este eliminador se construye por movimiento del eliminador de u (requiere que esta construcción no lance excepciones).
Este constructor solo participa en la resolución de sobrecarga si todo lo siguiente es verdadero:
a) unique_ptr<U, E>::pointer es convertible implícitamente a pointer;
b) U no es un tipo array;
c) ya sea que Deleter es un tipo referencia y E es el mismo tipo que D, o Deleter no es un tipo referencia y E es convertible implícitamente a D.
6) En la especialización para arrays se comporta igual que en la plantilla primaria, excepto que solo participará en la resolución de sobrecarga si todo lo siguiente es verdadero
  • U es un tipo array;
  • pointer es el mismo tipo que element_type*;
  • unique_ptr<U,E>::pointer es el mismo tipo que unique_ptr<U,E>::element_type*;
  • unique_ptr<U,E>::element_type(*)[] es convertible a element_type(*)[];
  • ya sea que Deleter es un tipo referencia y E es el mismo tipo que Deleter, o Deleter no es un tipo referencia y E es convertible implícitamente a Deleter.
7) Construye un std::unique_ptr donde el puntero almacenado se inicializa con u.release() y el eliminador 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 el mismo tipo que std::default_delete<T>.

Parámetros

p - Un puntero a un objeto a gestionar.
d1,d2 - Un eliminador a usar para destruir el objeto.
u - Otro puntero inteligente del cual adquirir la posesión.

Notas

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

(desde C++14)

std::unique_ptr<Derived> es convertible implícitamente a std::unique_ptr<Base> a través de la sobrecarga (6) (porque tanto el puntero gestionado como std::default_delete son convertibles implícitamente).

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

No hay deducción de argumentos de plantillas de clase de un tipo puntero porque es imposible distinguir un puntero obtenido de las formas array y no array de new.

(desde C++17)

Ejemplo

#include <iostream>
#include <memory>

struct Foo { // objeto a gestionar
    Foo() { std::cout << "ctor de Foo\n"; }
    Foo(const Foo&) { std::cout << "ctor de copia de Foo\n"; }
    Foo(Foo&&) { std::cout << "ctor de movimiento de Foo\n"; }
    ~Foo() { std::cout << "dtor de Foo\n"; }
};

struct D { // eliminador
    D() {};
    D(const D&) { std::cout << "ctor de copia de D\n"; }
    D(D&) { std::cout << "ctor de copia no const de D\n";}
    D(D&&) { std::cout << "ctor de movimiento de D\n"; }
    void operator()(Foo* p) const {
        std::cout << "D está eliminando un objeto Foo\n";
        delete p;
    };
};

int main()
{
    std::cout << "Ejemplo 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 objeto Foo
    } // Foo eliminado

    std::cout << "Ejemplo constructor(3)...\n";
    D d;
    {  // el tipo del eliminador no es una referencia
       std::unique_ptr<Foo, D> up3(new Foo, d); // eliminador copiado
    }
    {  // el tipo del eliminador es una referencia 
       std::unique_ptr<Foo, D&> up3b(new Foo, d); // up3b mantiene una referencia a d
    }

    std::cout << "Ejemplo constructor(4)...\n";
    {  // el eliminador no es una referencia 
       std::unique_ptr<Foo, D> up4(new Foo, D()); // eliminador movido
    }

    std::cout << "Ejemplo constructor(5)...\n";
    {
       std::unique_ptr<Foo> up5a(new Foo);
       std::unique_ptr<Foo> up5b(std::move(up5a)); // transferencia de posesión
    }

    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 mueve

        std::unique_ptr<Foo, D&> up6c(new Foo, d); // D es una referencia
        std::unique_ptr<Foo, D> up6d(std::move(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::move(up7a)); // transferencia de posesión
    }
#endif

    std::cout << "Ejemplo constructor forma array...\n";
    {
        std::unique_ptr<Foo[]> up(new Foo[3]);
    } // tres objetos Foo eliminados
}

Salida:

Ejemplo constructor(1)...
Ejemplo constructor(2)...
ctor de Foo
dtor de Foo
Ejemplo constructor(3)...
ctor de Foo
ctor de copia de D
D está eliminando un objeto Foo
dtor de Foo
ctor de Foo
D está eliminando un objeto Foo
dtor de Foo
Ejemplo constructor(4)...
ctor de Foo
ctor de movimiento de D
D está eliminando un objeto Foo
dtor de Foo
Ejemplo constructor(5)...
ctor de Foo
dtor de Foo
Ejemplo constructor(6)...
ctor de Foo
ctor de copia de D
ctor de movimiento de D
ctor de Foo
ctor de copia no const de D
D está eliminando un objeto Foo
dtor de Foo
D está eliminando un objeto Foo
dtor de Foo
Ejemplo constructor(7)...
ctor de Foo
dtor de Foo
Ejemplo constructor forma array...
ctor de Foo
ctor de Foo
ctor de Foo
dtor de Foo
dtor de Foo
dtor de Foo

Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 2118 C++11 Los constructores de unique_ptr<T[]> rechazaban las conversiones de calificación. Las aceptan.
LWG 2520 C++11 unique_ptr<T[]> se hizo accidentalmente no construible a partir de nullptr_t Se hizo construible.
LWG 2801 C++11 El constructor por defecto no estaba restringido. Se restringió.
LWG 2899 C++11 El constructor de movimiento no estaba restringido. Se restringió.
LWG 2905 C++11 La restricción en el constructor de un puntero y un eliminador estaba equivocada. Se corrigió.
LWG 2944 C++11 Algunas precondiciones se eliminaron accidentalmente por LWG 2905. Se restauraron.