std:: make_shared, std:: make_shared_for_overwrite
|
Definido en el encabezado
<memory>
|
||
|
template
<
class
T,
class
...
Args
>
shared_ptr < T > make_shared ( Args && ... args ) ; |
(1) | (desde C++11) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( std:: size_t N ) ; |
(2) | (desde C++20) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( ) ; |
(3) | (desde C++20) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( std:: size_t N, const std:: remove_extent_t < T > & u ) ; |
(4) | (desde C++20) |
|
template
<
class
T
>
shared_ptr < T > make_shared ( const std:: remove_extent_t < T > & u ) ; |
(5) | (desde C++20) |
|
template
<
class
T
>
shared_ptr < T > make_shared_for_overwrite ( ) ; |
(6) | (desde C++20) |
|
template
<
class
T
>
shared_ptr < T > make_shared_for_overwrite ( std:: size_t N ) ; |
(7) | (desde C++20) |
Asigna memoria para un objeto e inicializa el objeto con los argumentos proporcionados. Retorna un std::shared_ptr que gestiona el objeto recién creado.
T
, y se construye como si mediante
::
new
(
pv
)
T
(
std::
forward
<
Args
>
(
args
)
...
)
, 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 mediante
pt
-
>
~T
(
)
, donde
pt
es un puntero a ese objeto de tipo
T
.
|
Esta sobrecarga participa en la resolución de sobrecarga solo si
|
(since C++20) |
T
es un tipo de array sin límite.
T
. Cada elemento tiene un valor inicial predeterminado.
T
es un tipo de array con límites definidos.
T
es un tipo de array sin límite.
T
. Cada elemento tiene el valor inicial
u
.
T
es un tipo de array acotado.
T
.
-
Si
Tno 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 tipoT. Si el objeto debe ser destruido, se destruye como si fuera mediante pt - > ~T ( ) , donde pt es un puntero a ese objeto de tipoT. -
Si
Tes un tipo de arreglo de tamaño fijo, el valor inicial no está especificado para cada elemento.
T
no es un tipo de array o es un tipo de array con límites definidos.
T
es un tipo de array sin límite.
Inicialización y destrucción de elementos de array
Los elementos del array de tipo
2,3)
::
new
(
pv
)
U
(
)
4,5)
::
new
(
pv
)
U
(
u
)
6,7)
::
new
(
pv
)
U
Cuando finaliza el tiempo de vida del objeto gestionado por el std::shared_ptr retornado, o cuando la inicialización de un elemento del array lanza una excepción, los elementos inicializados se destruyen en el orden inverso a su construcción original.
Para cada elemento del array de tipo no-array
|
(desde C++20) |
Parámetros
| args | - |
lista de argumentos con los cuales se construirá un objeto 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
std::bad_alloc
o cualquier excepción lanzada por el constructor de
T
. Si se lanza una excepción, las funciones no tienen efecto.
Si se lanza una excepción durante la construcción del array, los elementos ya inicializados se destruyen en orden inverso.
(desde C++20)
Notas
Estas funciones normalmente asignarán más memoria que sizeof ( T ) para permitir estructuras internas de contabilidad como conteos de referencia.
Estas funciones pueden utilizarse como alternativa a std:: shared_ptr < T > ( new T ( args... ) ) . Las compensaciones son:
-
std::
shared_ptr
<
T
>
(
new T
(
args...
)
)
realiza al menos dos asignaciones de memoria (una para el objeto
Ty otra para el bloque de control del puntero compartido), mientras que std :: make_shared < T > típicamente realiza solo una asignación (el estándar recomienda, pero no requiere esto; todas las implementaciones conocidas lo hacen). -
Si algún
std::weak_ptr
referencia el bloque de control creado por
std::make_shareddespués de que finalice el tiempo de vida de todos los propietarios compartidos, la memoria ocupada porTpersiste hasta que todos los propietarios débiles también sean destruidos, lo cual puede ser indeseable si sizeof ( T ) es grande. -
std::
shared_ptr
<
T
>
(
new T
(
args...
)
)
puede llamar a un constructor no público de
Tsi se ejecuta en un contexto donde es accesible, mientras questd::make_sharedrequiere acceso público al constructor seleccionado. -
A diferencia de los constructores de
std::shared_ptr
,
std::make_sharedno permite un eliminador personalizado. -
std::make_sharedutiliza :: new , por lo que si se ha configurado algún comportamiento especial utilizando un operator new específico de clase, diferirá de std:: shared_ptr < T > ( new T ( args... ) ) .
|
(hasta C++20) |
|
(hasta C++17) |
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.
| Macro de prueba de características | Valor | Std | Característica |
|---|---|---|---|
__cpp_lib_shared_ptr_arrays
|
201707L
|
(C++20) |
Soporte para arrays de
std::make_shared
; sobrecargas
(
2-5
)
|
__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 <iostream> #include <memory> #include <type_traits> #include <vector> struct C { // constructores necesarios (hasta C++20) C(int i) : i(i) {} C(int i, float f) : i(i), f(f) {} int i; float f{}; }; int main() { // usando "auto" para el tipo de "sp1" auto sp1 = std::make_shared<C>(1); // sobrecarga (1) static_assert(std::is_same_v<decltype(sp1), std::shared_ptr<C>>); std::cout << "sp1->{ i:" << sp1->i << ", f:" << sp1->f << " }\n"; // siendo explícito con el tipo de “sp2” std::shared_ptr<C> sp2 = std::make_shared<C>(2, 3.0f); // sobrecarga (1) static_assert(std::is_same_v<decltype(sp2), std::shared_ptr<C>>); static_assert(std::is_same_v<decltype(sp1), decltype(sp2)>); std::cout << "sp2->{ i:" << sp2->i << ", f:" << sp2->f << " }\n"; // shared_ptr a un float[64] inicializado por valor; sobrecarga (2): std::shared_ptr<float[]> sp3 = std::make_shared<float[]>(64); // shared_ptr a un long[5][3][4] inicializado por valor; sobrecarga (2): std::shared_ptr<long[][3][4]> sp4 = std::make_shared<long[][3][4]>(5); // shared_ptr a un short[128] con inicialización de valor; sobrecarga (3): std::shared_ptr<short[128]> sp5 = std::make_shared<short[128]>(); // shared_ptr a un int[7][6][5] inicializado por valor; sobrecarga (3): std::shared_ptr<int[7][6][5]> sp6 = std::make_shared<int[7][6][5]>(); // shared_ptr a un double[256], donde cada elemento es 2.0; sobrecarga (4): std::shared_ptr<double[]> sp7 = std::make_shared<double[]>(256, 2.0); // shared_ptr a un double[7][2], donde cada double[2] // elemento es {3.0, 4.0}; sobrecarga (4): std::shared_ptr<double[][2]> sp8 = std::make_shared<double[][2]>(7, {3.0, 4.0}); // shared_ptr a un vector<int>[4], donde cada vector // tiene contenido {5, 6}; sobrecarga (4): std::shared_ptr<std::vector<int>[]> sp9 = std::make_shared<std::vector<int>[]>(4, {5, 6}); // shared_ptr a un float[512], donde cada elemento es 1.0; sobrecarga (5): std::shared_ptr<float[512]> spA = std::make_shared<float[512]>(1.0); // shared_ptr a un double[6][2], donde cada elemento double[2] // es {1.0, 2.0}; sobrecarga (5): std::shared_ptr<double[6][2]> spB = std::make_shared<double[6][2]>({1.0, 2.0}); // shared_ptr a un vector<int>[4], donde cada vector // tiene contenido {5, 6}; sobrecarga (5): std::shared_ptr<std::vector<int>[4]> spC = std::make_shared<std::vector<int>[4]>({5, 6}); }
Salida:
sp1->{ i:1, f:0 }
sp2->{ i:2, f:3 }
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 4024 | C++20 |
no estaba claro cómo se destruyen los objetos construidos en
std::make_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 asignado usando un asignador
(plantilla de función) |
|
|
(C++11)
|
permite que un objeto cree un
shared_ptr
que haga referencia a sí mismo
(plantilla de clase) |
|
(C++14)
(C++20)
|
crea un puntero único que gestiona un nuevo objeto
(plantilla de función) |
|
funciones de asignación
(función) |