Namespaces
Variants

std:: allocate_shared, std:: allocate_shared_for_overwrite

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)
Definido en el encabezado <memory>
template < class T, class Alloc, class ... Args >
shared_ptr < T > allocate_shared ( const Alloc & alloc, Args && ... args ) ;
(1) (desde C++11)
template < class T, class Alloc >
shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N ) ;
(2) (desde C++20)
template < class T, class Alloc >
shared_ptr < T > allocate_shared ( const Alloc & alloc ) ;
(3) (desde C++20)
template < class T, class Alloc >

shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N,

const std:: remove_extent_t < T > & u ) ;
(4) (desde C++20)
template < class T, class Alloc >

shared_ptr < T > allocate_shared ( const Alloc & alloc,

const std:: remove_extent_t < T > & u ) ;
(5) (desde C++20)
template < class T, class Alloc >
shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc ) ;
(6) (desde C++20)
template < class T, class Alloc >

shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc,

std:: size_t N ) ;
(7) (desde C++20)

Asigna memoria para un objeto utilizando una copia de alloc (reconfigurado para un value_type no especificado) e inicializa el objeto con los argumentos proporcionados. Retorna un objeto std::shared_ptr que gestiona el objeto recién creado.

1) El objeto es de tipo T , y se construye como si mediante std:: allocator_traits < Alloc > :: construct
( a, pt, ( std:: forward < Args > ( args ) ... )
, donde pt es un std:: remove_cv_t < T > * puntero a almacenamiento adecuado para contener un objeto de tipo std:: remove_cv_t < T > . Si el objeto debe ser destruido, se destruye como si mediante std:: allocator_traits < Alloc > :: destroy ( a, pt ) , donde pt es un puntero a ese objeto de tipo std:: remove_cv_t < T > .
En la descripción anterior, a es de tipo Alloc , y es una copia potencialmente reenlazada de alloc .

Esta sobrecarga participa en la resolución de sobrecarga solo si T no es un tipo array.

(since C++20)
2) El objeto es de tipo std:: remove_extent_t < T > [ N ] . Cada elemento tiene un valor inicial por defecto.
Esta sobrecarga participa en la resolución de sobrecarga solo si T es un tipo de array sin límite.
3) El objeto es de tipo T . Cada elemento tiene un valor inicial predeterminado.
Esta sobrecarga participa en la resolución de sobrecarga solo si T es un tipo de array acotado.
4) El objeto es de tipo std:: remove_extent_t < T > [ N ] . Cada elemento tiene el valor inicial u .
Esta sobrecarga participa en la resolución de sobrecarga solo si T es un tipo de array sin límite.
5) El objeto es de tipo T . Cada elemento tiene el valor inicial u .
Esta sobrecarga participa en la resolución de sobrecarga solo si T es un tipo de array acotado.
6) El objeto es de tipo T .
  • Si T no es un tipo de arreglo, el objeto se construye como si fuera mediante :: new ( pv ) T , donde pv es un puntero void * a almacenamiento adecuado para contener un objeto de tipo T . Si el objeto debe ser destruido, se destruye como si fuera mediante pt - > ~T ( ) , donde pt es un puntero a ese objeto de tipo T .
  • Si T es un tipo de arreglo con límites definidos, el valor inicial no está especificado para cada elemento.
Esta sobrecarga participa en la resolución de sobrecarga solo si T no es un tipo de array o es un tipo de array con límites definidos.
7) El objeto es de tipo std:: remove_extent_t < T > [ N ] . El valor inicial no está especificado para cada elemento.
Esta sobrecarga participa en la resolución de sobrecarga solo si T es un tipo de matriz sin límite.

Contenidos

Inicialización y destrucción de elementos de array

En la descripción a continuación, a es de tipo Alloc , y es una copia potencialmente reenlazada de alloc .

Los elementos de array de tipo U se inicializan en orden ascendente de sus direcciones.

  • Si U no es un tipo array, cada elemento se construye como si mediante la siguiente expresión, donde pu es un puntero std:: remove_cv_t < U > * a almacenamiento adecuado para contener un objeto de tipo std:: remove_cv_t < U > , y pv es un puntero void * a almacenamiento adecuado para contener un objeto de tipo U :
2,3) std:: allocator_traits < Alloc > :: construct ( a, pu )
4,5) std:: allocator_traits < Alloc > :: construct ( a, pu, u )
6,7) :: new ( pv ) U
  • De lo contrario, inicializa recursivamente los elementos de cada elemento. Para la siguiente dimensión:
  • U se convierte en std:: remove_extent_t < U > .
  • Para las sobrecargas (4,5) , u se convierte en el elemento correspondiente de u .

Cuando finaliza el tiempo de vida del objeto gestionado por el std::shared_ptr retornado, o cuando la inicialización de un elemento de array lanza una excepción, los elementos inicializados se destruyen en el orden inverso a su construcción original.

Para cada elemento de array de tipo no-array U a destruir, se destruye como si mediante la siguiente expresión:

2-5) std:: allocator_traits < Alloc > :: destroy ( a, pu ) , donde pu es un puntero U * a ese elemento de array de tipo U
6,7) pu - > ~U ( ) , donde pu es un puntero a ese elemento de array de tipo U
(desde C++20)

Parámetros

alloc - el Allocator a utilizar
args... - lista de argumentos con los cuales se construirá una instancia de T
N - tamaño del array a utilizar
u - el valor inicial para inicializar cada elemento del array

Valor de retorno

std::shared_ptr a un objeto de tipo T o std:: remove_extent_t < T > [ N ] si T es un tipo de array sin límite (desde C++20) .

Para el std::shared_ptr r devuelto, r. get ( ) retorna un puntero no nulo y r. use_count ( ) retorna 1 .

Excepciones

Puede lanzar las excepciones lanzadas desde Alloc :: allocate ( ) o desde el constructor de T . Si se lanza una excepción, (1) no tiene efecto. Si se lanza una excepción durante la construcción del array, los elementos ya inicializados se destruyen en orden inverso (since C++20) .

Notas

Estas funciones normalmente asignarán más memoria que sizeof ( T ) para permitir estructuras internas de contabilidad como conteos de referencia.

Al igual que std::make_shared , esta función normalmente realiza solo una asignación, y coloca tanto el objeto T como el bloque de control en el bloque de memoria asignado (el estándar recomienda pero no requiere esto, todas las implementaciones conocidas lo hacen). Una copia de alloc se almacena como parte del bloque de control para que pueda usarse para desasignarlo una vez que tanto los contadores de referencia compartidos como débiles lleguen a cero.

A diferencia de los std::shared_ptr constructors , std::allocate_shared no acepta un deleter personalizado separado: el asignador proporcionado se utiliza para la destrucción del bloque de control y del objeto T , y para la desasignación de su bloque de memoria compartida.

std::shared_ptr admite tipos de array (desde C++17), pero std::allocate_shared no lo hace. Esta funcionalidad está soportada por boost::allocate_shared .

(hasta C++20)

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 concurrente potencial 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.

Macro de prueba de características Valor Std Característica
__cpp_lib_smart_ptr_for_overwrite 202002L (C++20) Creación de punteros inteligentes con inicialización por defecto ( std::allocate_shared_for_overwrite , std::make_shared_for_overwrite , std::make_unique_for_overwrite ); sobrecargas ( 6,7 )

Ejemplo

#include <cstddef>
#include <iostream>
#include <memory>
#include <memory_resource>
#include <vector>
class Value
{
    int i;
public:
    Value(int i) : i(i) { std::cout << "Value(), i = " << i << '\n'; }
    ~Value() { std::cout << "~Value(), i = " << i << '\n'; }
    void print() const { std::cout << "i = " << i << '\n'; }
};
int main()
{
    // Crear un asignador polimórfico usando el recurso de búfer monótono
    std::byte buffer[sizeof(Value) * 8];
    std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer));
    std::pmr::polymorphic_allocator<Value> allocator(&resource);
    std::vector<std::shared_ptr<Value>> v;
    for (int i{}; i != 4; ++i)
        // Usar std::allocate_shared con el asignador personalizado
        v.emplace_back(std::allocate_shared<Value>(allocator, i));
    for (const auto& sp : v)
        sp->print();
} //< Todos los shared pointers limpiarán automáticamente cuando salgan del ámbito.

Salida:

Value(), i = 0
Value(), i = 1
Value(), i = 2
Value(), i = 3
i = 0
i = 1
i = 2
i = 3
~Value(), i = 0
~Value(), i = 1
~Value(), i = 2
~Value(), i = 3

Informes de defectos

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

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 3216 C++20 std::allocate_shared siempre reenlazaba el
asignador antes de construir y destruir objetos
el reenlace es opcional
LWG 4024 C++20 no estaba claro cómo se destruyen los objetos construidos en
std::allocate_shared_for_overwrite
aclarado

Véase también

construye un nuevo shared_ptr
(función miembro pública)
crea un puntero compartido que gestiona un nuevo objeto
(plantilla de función)