Namespaces
Variants

std::shared_ptr<T>:: shared_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)
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 Y* es compatible con un tipo de puntero T* si Y* es convertible a T* o Y es el tipo de arreglo U[N] y T es U cv [] (donde cv es algún conjunto de calificadores cv).

(desde C++17)
1,2) Construye un shared_ptr sin objeto gestionado, es decir, un shared_ptr vacío.
3-7) Construye un shared_ptr con ptr como el puntero al objeto gestionado.

Para (3,4,6) , Y* debe ser convertible a T* .

(hasta C++17)

Si T es un tipo de arreglo U[N] , (3,4,6) no participan en la resolución de sobrecarga si Y(*)[N] es un tipo inválido o no convertible a T* . Si T es un tipo de arreglo U[] , (3,4,6) no participan en la resolución de sobrecarga si Y(*)[] es un tipo inválido o no convertible a T* . En otro caso, (3,4,6) no participan en la resolución de sobrecarga si Y* no es convertible a T* .

(desde C++17)
Adicionalmente:
3) Utiliza la expresión delete delete ptr si 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)
4,5) Utiliza el deleter especificado d como el deleter. La expresión d ( ptr ) debe estar bien formada, tener un comportamiento bien definido y no lanzar excepciones. La construcción de d y del deleter almacenado copiado de este no debe lanzar excepciones.

Deleter debe ser CopyConstructible .

(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)
6,7) Igual que (4,5) , pero adicionalmente utiliza una copia de alloc para la asignación de datos para uso interno. Alloc debe ser un Allocator .
8) El constructor de aliasing : construye un 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)
9) Construye un 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* .
10) Construye por movimiento un 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* .
11) Construye un 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.
12) Construye un 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.
13) Construye un 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)
Si 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

1,2) use_count() es igual a 0 y get() es igual a nullptr .
3-7) use_count() es igual a 1 y get() es igual a ptr .
8) get() es igual a ptr . Para la segunda sobrecarga, r está vacío y r. get ( ) es igual a nullptr .
9) get() es igual a r. get ( ) y use_count() es igual a r. use_count ( ) .
10) r estará vacío y r. get ( ) será igual a nullptr , y * this será el valor anterior de r .
11) use_count() es igual a r. use_count ( ) .
12) use_count() es igual a 1 y r. get ( ) es igual a nullptr .

Excepciones

3) std::bad_alloc si no se pudo obtener la memoria adicional requerida. Puede lanzar excepciones definidas por la implementación para otros errores. Si ocurre una excepción, esto llama a delete ptr si T no es un tipo de array, y llama a delete [ ] ptr en caso contrario (desde C++17) .
4-7) std::bad_alloc si no se pudo obtener la memoria adicional requerida. Puede lanzar excepciones definidas por la implementación para otros errores. d ( ptr ) se llama si ocurre una excepción.
11) std::bad_weak_ptr si r. expired ( ) == true . El constructor no tiene efecto en este caso.
12) std::bad_alloc si no se pudo obtener la memoria adicional requerida. Puede lanzar excepciones definidas por la implementación para otros errores. Este constructor no tiene efecto si ocurre una excepción.
13) Si se lanza una excepción, el constructor no tiene efectos.

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)
permite que un objeto cree un shared_ptr que haga referencia a sí mismo
(plantilla de clase)