ptr compartido a una matriz: ¿debería usarse?
Sólo una pequeña consulta sobre shared_ptr
.
¿Es una buena práctica usar shared_ptr
apuntando a una matriz? Por ejemplo,
shared_ptr<int> sp(new int[10]);
Si no, entonces ¿por qué no? Una razón de la que ya soy consciente es que uno no puede incrementar/disminuir el shared_ptr
. Por lo tanto, no se puede utilizar como un puntero normal a una matriz.
2 answers
Por C++17, shared_ptr
se puede usar para administrar una matriz asignada dinámicamente. El argumento de la plantilla shared_ptr
en este caso debe ser T[N]
o T[]
. Así que usted puede escribir
shared_ptr<int[]> sp(new int[10]);
De n4659, [útil.smartptr.compartir.const]
template<class Y> explicit shared_ptr(Y* p);
Requiere:
Y
será un tipo completo. La expresióndelete[] p
, {cuando[18]} es un tipo de matriz, odelete p
, {cuando[18]} no es un tipo de matriz, se tiene bien definido el comportamiento, y no tirar salvedad.
...
Observaciones: CuandoT
es un tipo de matriz, este constructor no participará en la resolución de sobrecarga a menos que la expresióndelete[] p
esté bien formada yT
seaU[N]
yY(*)[N]
sea convertible aT*
, oT
seaU[]
yY(*)[]
es convertible aT*
. ...
Para soportar esto, el tipo miembroelement_type
se define ahora como
using element_type = remove_extent_t<T>;
Los elementos del array pueden ser accedidos usando operator[]
element_type& operator[](ptrdiff_t i) const;
Requiere:
get() != 0 && i >= 0
. SiT
esU[N]
,i < N
. ...
Observaciones: CuandoT
no es un tipo de matriz, no se especifica si se declara esta función miembro. Si se declara, no se especifica cuál es su tipo de retorno, excepto que la declaración (aunque no necesariamente la definición) de la función debe estar bien formada.
Antes de C++17, shared_ptr
se podría usar no para administrar arrays dinámicamente asignados. De forma predeterminada, shared_ptr
llamará a delete
en el objeto administrado cuando no queden más referencias a él. Sin embargo, cuando se asigna usando new[]
es necesario llamar a delete[]
, y no a delete
, para liberar el recurso.
Para usar correctamente shared_ptr
con una matriz, debe proporcionar un deleter personalizado.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Cree el shared_ptr de la siguiente manera:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Ahora shared_ptr
llamará correctamente a delete[]
al destruir el objeto administrado.
El deleter personalizado anterior puede ser reemplazado por
-
El
std::default_delete
especialización parcial para tipos de matricesstd::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
-
Una expresión lambda
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Además, a menos que realmente necesite compartir onwership del objeto administrado, un unique_ptr
es más adecuado para esta tarea, ya que tiene una especialización parcial para los tipos de matriz.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Cambios introducidos por las extensiones de C++ para los Fundamentos de Bibliotecas
Otra alternativa pre-C++17 a la los mencionados anteriormente fueron proporcionados por la Especificación Técnica Library Fundamentals , que aumentó shared_ptr
para permitir que funcione fuera de la caja para los casos en que posee una matriz de objetos. El borrador actual de los shared_ptr
cambios programados para este TS se puede encontrar en N4082. Estos cambios serán accesibles a través del espacio de nombres std::experimental
, e incluidos en el encabezado <experimental/memory>
. Algunos de los cambios relevantes para soportar shared_ptr
para arrays son:
- la definición de La tipo de miembro element_type
cambios
typedef T element_type;typedef typename remove_extent<T>::type element_type;
- Se añade el miembro operator[]
element_type& operator[](ptrdiff_t i) const noexcept;
- A diferencia de la especialización parcial de unique_ptr
para los arrays, tanto shared_ptr<T[]>
como shared_ptr<T[N]>
serán válidos y ambos resultarán en que delete[]
sea llamado en el array administrado de objetos.
template<class Y> explicit shared_ptr(Y* p);
Requiere:
Y
será un tipo completo. La expresióndelete[] p
, {cuando[18]} es un tipo de matriz, odelete p
, cuandoT
no es un tipo de matriz, debe estar bien formado, debe tener un comportamiento bien definido, y no debe lanzar excepciones. CuandoT
esU[N]
,Y(*)[N]
será convertible aT*
; cuandoT
seaU[]
,Y(*)[]
será convertible aT*
; de lo contrario,Y*
será convertible aT*
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-09 16:50:52
Una alternativa posiblemente más fácil que podría ser capaz de utilizar es shared_ptr<vector<int>>
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-03 13:06:39