std::unique_ptr::unique_ptr
| 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) |
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.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) |
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):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) |
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) | |
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) | |
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) |
Ues el mismo tipo quepointer, oUes std::nullptr_t, opointeres el mismo tipo queelement_type*yUes algún tipo punteroV*tal queV(*)[]es convertible implícitamente aelement_type(*)[].
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).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:E es un tipo referencia, este eliminador se construye por copia del eliminador de u (requiere que esta construcción no lance excepciones).E no es un tipo referencia, este eliminador se construye por movimiento del eliminador de u (requiere que esta construcción no lance excepciones).unique_ptr<U, E>::pointer es convertible implícitamente a pointer;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.Ues un tipo array;pointeres el mismo tipo queelement_type*;unique_ptr<U,E>::pointeres el mismo tipo queunique_ptr<U,E>::element_type*;unique_ptr<U,E>::element_type(*)[]es convertible aelement_type(*)[];- ya sea que
Deleteres un tipo referencia yEes el mismo tipo queDeleter, oDeleterno es un tipo referencia yEes convertible implícitamente aDeleter.
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 |
(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 |
(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. |