std::shared_ptr<T>:: shared_ptr
|
constexpr
shared_ptr
(
)
noexcept
;
|
(1) | |
|
constexpr
shared_ptr
(
std::
nullptr_t
)
noexcept
;
|
(2) | |
|
template
<
class
Y
>
explicit shared_ptr ( Y * ptr ) ; |
(3) | |
|
template
<
class
Y,
class
Deleter
>
shared_ptr ( Y * ptr, Deleter d ) ; |
(4) | |
|
template
<
class
Deleter
>
shared_ptr ( std:: nullptr_t ptr, Deleter d ) ; |
(5) | |
|
template
<
class
Y,
class
Deleter,
class
Alloc
>
shared_ptr ( Y * ptr, Deleter d, Alloc alloc ) ; |
(6) | |
|
template
<
class
Deleter,
class
Alloc
>
shared_ptr ( std:: nullptr_t ptr, Deleter d, Alloc alloc ) ; |
(7) | |
|
template
<
class
Y
>
shared_ptr ( const shared_ptr < Y > & r, element_type * ptr ) noexcept ; |
(8) | |
|
template
<
class
Y
>
shared_ptr ( shared_ptr < Y > && r, element_type * ptr ) noexcept ; |
(8) | (desde C++20) |
|
shared_ptr
(
const
shared_ptr
&
r
)
noexcept
;
|
(9) | |
|
template
<
class
Y
>
shared_ptr ( const shared_ptr < Y > & r ) noexcept ; |
(9) | |
|
shared_ptr
(
shared_ptr
&&
r
)
noexcept
;
|
(10) | |
|
template
<
class
Y
>
shared_ptr ( shared_ptr < Y > && r ) noexcept ; |
(10) | |
|
template
<
class
Y
>
explicit shared_ptr ( const std:: weak_ptr < Y > & r ) ; |
(11) | |
|
template
<
class
Y
>
shared_ptr ( std:: auto_ptr < Y > && r ) ; |
(12) | (eliminado en C++17) |
|
template
<
class
Y,
class
Deleter
>
shared_ptr ( std:: unique_ptr < Y, Deleter > && r ) ; |
(13) | |
Construye un nuevo
shared_ptr
a partir de varios tipos de punteros que referencian un objeto a gestionar.
|
Para los propósitos de la descripción a continuación, se dice que un tipo de puntero
|
(desde C++17) |
shared_ptr
sin objeto gestionado, es decir, un
shared_ptr
vacío.
shared_ptr
con
ptr
como el puntero al objeto gestionado.
|
Para
(3,4,6)
,
|
(hasta C++17) |
|
Si
|
(desde C++17) |
T
no es un tipo array;
delete
[
]
ptr
si
T
es un tipo array
(desde C++17)
como el eliminador.
Y
debe ser un tipo completo. La expresión delete debe estar bien formada, tener un comportamiento bien definido y no lanzar ninguna excepción.
Este constructor adicionalmente no participa en la resolución de sobrecarga si la expresión delete no está bien formada.
(desde C++17)
|
|
(hasta C++17) |
|
Estos constructores adicionalmente no participan en la resolución de sobrecarga si la expresión d ( ptr ) no está bien formada, o si std:: is_move_constructible_v < D > es false . |
(desde C++17) |
Alloc
debe ser un
Allocator
.
shared_ptr
que comparte información de propiedad con el valor inicial de
r
, pero mantiene un puntero no relacionado y no gestionado
ptr
. Si este
shared_ptr
es el último del grupo en salir del ámbito, llamará al eliminador almacenado para el objeto originalmente gestionado por
r
. Sin embargo, llamar a
get()
en este
shared_ptr
siempre devolverá una copia de
ptr
. Es responsabilidad del programador asegurar que este
ptr
permanezca válido mientras este shared_ptr exista, como en los casos de uso típicos donde
ptr
es un miembro del objeto gestionado por
r
o es un alias (por ejemplo, downcast) de
r.get()
Para la segunda sobrecarga que toma un rvalue,
r
está vacío y
r.
get
(
)
==
nullptr
después de la llamada.
(desde C++20)
shared_ptr
que comparte la propiedad del objeto gestionado por
r
. Si
r
no gestiona ningún objeto,
*
this
tampoco gestiona ningún objeto. La sobrecarga de plantilla no participa en la resolución de sobrecarga si
Y*
no es
implícitamente convertible a
(hasta C++17)
compatible con
(desde C++17)
T*
.
shared_ptr
desde
r
. Después de la construcción,
*
this
contiene una copia del estado previo de
r
,
r
está vacío y su puntero almacenado es nulo. La sobrecarga de plantilla no participa en la resolución de sobrecarga si
Y*
no es
implícitamente convertible a
(until C++17)
compatible con
(since C++17)
T*
.
shared_ptr
que comparte la propiedad del objeto gestionado por
r
.
Y*
debe ser convertible implícitamente a
T*
.
(hasta C++17)
Esta sobrecarga participa en la resolución de sobrecarga solo si
Y*
es compatible con
T*
.
(desde C++17)
Nótese que
r.
lock
(
)
puede usarse para el mismo propósito: la diferencia es que este constructor lanza una excepción si el argumento está vacío, mientras que
std::
weak_ptr
<
T
>
::
lock
(
)
construye un
std::shared_ptr
vacío en ese caso.
shared_ptr
que almacena y posee el objeto anteriormente propiedad de
r
.
Y*
debe ser convertible a
T*
. Después de la construcción,
r
está vacío.
shared_ptr
que gestiona el objeto actualmente gestionado por
r
. El deleter asociado con
r
se almacena para la futura eliminación del objeto gestionado.
r
no gestiona ningún objeto después de la llamada.
Esta sobrecarga no participa en la resolución de sobrecarga si
std::unique_ptr<Y, Deleter>::pointer
no es
compatible con
T*
.
Si
r.
get
(
)
es un puntero nulo, esta sobrecarga es equivalente al constructor por defecto
(1)
.
|
(desde C++17) |
Deleter
es un tipo de referencia, es equivalente a
shared_ptr
(
r.
release
(
)
,
std::
ref
(
r.
get_deleter
(
)
)
. De lo contrario, es equivalente a
shared_ptr
(
r.
release
(
)
, std
::
move
(
r.
get_deleter
(
)
)
)
.
Cuando
T
no es un tipo de arreglo, las sobrecargas
(3,4,6)
habilitan
shared_from_this
con
ptr
, y la sobrecarga
(13)
habilita
shared_from_this
con el puntero devuelto por
r.
release
(
)
.
Contenidos |
Parámetros
| ptr | - | un puntero a un objeto a gestionar |
| d | - | un deleter para usar al destruir el objeto |
| alloc | - | un allocator para usar en asignaciones de datos para uso interno |
| r | - | otro puntero inteligente con el que compartir la propiedad o del que adquirir la propiedad |
Postcondiciones
Excepciones
T
no es un tipo de array, y llama a
delete
[
]
ptr
en caso contrario
(desde C++17)
.
Notas
Un constructor
habilita
shared_from_this
con un puntero
ptr
de tipo
U*
significa que determina si
U
tiene una clase base
inequívoca y accesible
(desde C++17)
que sea una especialización de
std::enable_shared_from_this
, y si es así, el constructor evalúa
if
(
ptr
!
=
nullptr
&&
ptr
-
>
weak_this
.
expired
(
)
)
ptr
-
>
weak_this
=
std::
shared_ptr
<
std::
remove_cv_t
<
U
>>
(
*
this,
const_cast
<
std::
remove_cv_t
<
U
>
*
>
(
ptr
)
)
;
.
La asignación a
weak_this
no es atómica y entra en conflicto con cualquier acceso potencialmente concurrente al mismo objeto. Esto garantiza que futuras llamadas a
shared_from_this()
compartirían la propiedad con el
std::shared_ptr
creado por este constructor de puntero en bruto.
La prueba
ptr
-
>
weak_this
.
expired
(
)
en el código anterior asegura que
weak_this
no sea reasignado si ya indica un propietario. Esta prueba es requerida a partir de C++17.
Las sobrecargas de puntero crudo asumen la propiedad del objeto apuntado. Por lo tanto, construir un
shared_ptr
usando la sobrecarga de puntero crudo para un objeto que ya está gestionado por un
shared_ptr
, como por
shared_ptr
(
ptr.
get
(
)
)
probablemente conducirá a comportamiento indefinido, incluso si el objeto es de un tipo derivado de
std::enable_shared_from_this
.
Debido a que el constructor por defecto es
constexpr
, los shared_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 shared_ptr en el constructor de cualquier objeto estático.
En C++11 y C++14 es válido construir un std:: shared_ptr < T > a partir de un std:: unique_ptr < T [ ] > :
std::unique_ptr<int[]> arr(new int[1]); std::shared_ptr<int> ptr(std::move(arr));
Dado que el
shared_ptr
obtiene su eliminador (un objeto
std::
default_delete
<
T
[
]
>
) del
std::unique_ptr
, el array será correctamente desasignado.
Esto ya no está permitido en C++17. En su lugar, debería usarse la forma de array std:: shared_ptr < T [ ] > .
Ejemplo
#include <iostream> #include <memory> struct Foo { int id{0}; Foo(int i = 0) : id{i} { std::cout << "Foo::Foo(" << i << ")\n"; } ~Foo() { std::cout << "Foo::~Foo(), id=" << id << '\n'; } }; struct D { void operator()(Foo* p) const { std::cout << "Call delete from function object. Foo::id=" << p->id << '\n'; delete p; } }; int main() { { std::cout << "1) constructor with no managed object\n"; std::shared_ptr<Foo> sh1; } { std::cout << "2) constructor with object\n"; std::shared_ptr<Foo> sh2(new Foo{10}); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::shared_ptr<Foo> sh3(sh2); std::cout << "sh2.use_count(): " << sh2.use_count() << '\n'; std::cout << "sh3.use_count(): " << sh3.use_count() << '\n'; } { std::cout << "3) constructor with object and deleter\n"; std::shared_ptr<Foo> sh4(new Foo{11}, D()); std::shared_ptr<Foo> sh5(new Foo{12}, [](auto p) { std::cout << "Call delete from lambda... p->id=" << p->id << '\n'; delete p; }); } }
Salida:
1) constructor with no managed object 2) constructor with object Foo::Foo(10) sh2.use_count(): 1 sh2.use_count(): 2 sh3.use_count(): 2 Foo::~Foo(), id=10 3) constructor with object and deleter Foo::Foo(11) Foo::Foo(12) Call delete from lambda... p->id=12 Foo::~Foo(), id=12 Call delete from function object. Foo::id=11 Foo::~Foo(), id=11
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 3548 | C++11 |
el constructor desde
unique_ptr
copiaba-construía el deleter
|
mueve-construye en su lugar |
Véase también
|
crea un shared pointer que gestiona un nuevo objeto
(plantilla de función) |
|
|
crea un shared pointer que gestiona un nuevo objeto asignado usando un allocator
(plantilla de función) |
|
|
(C++11)
|
permite que un objeto cree un
shared_ptr
que haga referencia a sí mismo
(plantilla de clase) |