std::make_shared, std::make_shared_for_overwrite
Definido en el archivo de encabezado <memory>
|
||
template< class T, class... Args > shared_ptr<T> make_shared( Args&&... args ); |
(1) | (desde C++11) (T es no array) |
template< class T > shared_ptr<T> make_shared( std::size_t N ); |
(2) | (desde C++20) (T es U[]) |
template< class T > shared_ptr<T> make_shared(); |
(3) | (desde C++20) (T es U[N]) |
template< class T > shared_ptr<T> make_shared( std::size_t N, const std::remove_extent_t<T>& u ); |
(4) | (desde C++20) (T es U[]) |
template< class T > shared_ptr<T> make_shared( const std::remove_extent_t<T>& u ); |
(5) | (desde C++20) (T es U[N]) |
template< class T > shared_ptr<T> make_shared_for_overwrite(); |
(6) | (desde C++20) (T es not U[]) |
template< class T > shared_ptr<T> make_shared_for_overwrite( std::size_t N ); |
(7) | (desde C++20) (T es U[]) |
T
y lo envuelve en un std::shared_ptr usando args
como la lista de parámetros para el constructor de T
. El objeto se construye como si fuera por la expresión ::new (pv) T(std::forward<Args>(args)...), donde pv
es un puntero interno void* al almacenamiento adecuado para contener un objeto de tipo T
. El almacenamiento suele ser más grande que sizeof(T)
para usar una asignación tanto para el bloque de control del puntero compartido como para el objeto T
. El constructor std::shared_ptr llamado por esta función habilita shared_from_this
con un puntero al objeto recién construido de tipo T
.
Esta sobrecarga solo participa en la resolución de sobrecargas si T no es un tipo array. |
(desde C++20) |
std::remove_all_extents_t<T>
se inicializan como si fuera por la expresión new
de ubicación ::new(pv) std::remove_all_extents_t<T>(). La sobrecarga (2) crea un array de tamaño N
a lo largo de su primera dimensión. Los elementos del array se inicializan en orden ascendente de sus direcciones y, cuando finaliza su tiempo de vida, se destruyen en el orden inverso al de su construcción original.u
. Si U
no es un tipo array, entonces esto se realiza como si fuera por la misma expresión new
de ubicación que en (1); de lo contrario, esto se realiza como si se inicializaran todos los elementos que no son de tipo array del array (posiblemente multidimensional) con el elemento correspondiente de u
con la misma expresión new
de ubicación que en (1). La sobrecarga (4) crea un array de tamaño N
a lo largo de su primera dimensión. Los elementos del array se inicializan en orden ascendente de sus direcciones y, cuando finaliza su tiempo de vida, se destruyen en el orden inverso al de su construcción original.T
no es un tipo array y (3) si T
es U[N]
, excepto que el objeto creado es inicializado por defecto.En cada caso, el objeto (o elementos individuales si T
es un tipo array) (desde C++20) se destruirá por p->~X(), donde p
es un puntero al objeto y X
es su tipo.
Contenido |
[editar] Parámetros
args | - | Lista de argumentos con los que se construirá una instancia de T .
|
N | - | Tamaño de array a usar. |
u | - | El valor inicial con el que inicializar cada elemento del array. |
[editar] Valor de retorno
std::shared_ptr de una instancia de tipo T
.
[editar] 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 de del array, los elementos ya inicializados se destruyen en orden inverso. (desde C++20)
[editar] Notas
Esta función se puede utilizar 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 (uno para el objeto
T
y otra para el bloque de control del puntero compartido), mientras que std::make_shared<T> generalmente realiza solo una asignación (el estándar recomienda, pero no requiere esto; todas las implementaciones conocidas hacen esto). - Si algún std::weak_ptr hace referencia al bloque de control creado por
std::make_shared
después de que finalizó el tiempo de vida de todos los propietarios compartidos, la memoria ocupada porT
persiste hasta todos los propietarios débiles también son destruidos, lo que puede ser indeseable sisizeof(T)
es grande. - std::shared_ptr<T>(new T(args...)) puede llamar a un constructor no público de
T
si se ejecuta en un contexto donde es accesible, mientras questd::make_shared
requiere acceso público al constructor seleccionado. - A diferencia de los constructores de std::shared_ptr,
std::make_shared
no permite un eliminador personalizado. -
std::make_shared
usa ::new, por lo que si se ha configurado algún comportamiento especial usando un operator new específico de la clase, diferirá de std::shared_ptr<T>(new T(args...)).
|
(hasta C++20) |
|
(hasta C++17) |
Cuando se dice que un constructor habilita shared_from_this
con un puntero ptr
de tipo U*
, significa que determina si U
tiene una clase base no ambigua y accesible (desde C++17) que es una especialización de std::enable_shared_from_this, y si es así, el constructor evalúa la declaración:
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));
Donde weak_this
es el miembro std::weak_ptr mutable oculto de std::enable_shared_from_this. La asignación al miembro weak_this
no es atómica y entra en conflicto con cualquier acceso potencialmente concurrente al mismo objeto. Esto garantiza que las llamadas futuras a shared_from_this() compartirán la posesión con el std::shared_ptr creado por este constructor de puntero sin formato.
La prueba ptr->weak_this.expired() en el código de exposición anterior asegura que weak_this
no se reasigna si ya indica un propietario. Esta prueba es necesaria a partir de C++17.
Macro de Prueba de característica |
---|
__cpp_lib_shared_ptr_arrays
|
Macro de Prueba de característica |
---|
__cpp_lib_smart_ptr_for_overwrite
|
[editar] Ejemplo
#include <memory> #include <vector> #include <iostream> #include <type_traits> 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"; // véase https://wandbox.org/permlink/wVZT5Gl2omZrhxte // 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] inicializado por 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 elemento double[2] 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 el 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 el 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 }
[editar] 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++14)(C++20) |
Crea un puntero único que gestiona a un nuevo objeto. (plantilla de función) |
Funciones de asignación. (función) |