Con C ++ 17 , shared_ptrse puede usar para administrar una matriz asignada dinámicamente. El shared_ptrargumento de plantilla en este caso debe ser T[N]o T[]. Entonces puedes escribir
shared_ptr<int[]> sp(new int[10]);
Desde n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requiere: Y debe ser un tipo completo. La expresión delete[] p, cuando Tes un tipo de matriz o delete p, cuando Tno es un tipo de matriz, tendrá un comportamiento bien definido y no arrojará excepciones.
...
Observaciones: Cuando Tes un tipo de matriz, este constructor no podrá participar en la resolución de sobrecarga a menos que la expresión delete[] pestá bien formado y, o bien Tes U[N]y Y(*)[N]es convertible a T*, o Tes
U[], y Y(*)[]se puede convertir en T*. ...
Para admitir esto, el tipo de miembro element_typeahora se define como
using element_type = remove_extent_t<T>;
Se puede acceder a los elementos de la matriz utilizando operator[]
element_type& operator[](ptrdiff_t i) const;
Se requiere: get() != 0 && i >= 0 . Si Tes U[N], i < N. ...
Observaciones: cuando Tno 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 estará bien formada.
Antes de C ++ 17 , shared_ptrpodría no ser utilizado para administrar matrices dinámicamente asignados. Por defecto, shared_ptrllamará deleteal objeto administrado cuando no queden más referencias a él. Sin embargo, cuando asigna utilizando new[]debe llamar delete[], y no delete, para liberar el recurso.
Para usar correctamente shared_ptrcon una matriz, debe proporcionar un eliminador 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_ptrllamará correctamente delete[]al destruir el objeto administrado.
El eliminador personalizado anterior puede ser reemplazado por
la std::default_deleteespecialización parcial para tipos de matriz
std::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 la responsabilidad del objeto administrado, a unique_ptres 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 la biblioteca
Otra especificación anterior a C ++ 17 a las enumeradas anteriormente fue proporcionada por la Especificación técnica de los fundamentos de la biblioteca , que aumentó shared_ptrpara permitirle trabajar de forma inmediata para los casos en que posee una matriz de objetos. El borrador actual de los shared_ptrcambios programados para este TS se puede encontrar en N4082 . Se podrá acceder a estos cambios a través del std::experimentalespacio de nombres y se incluirán en el <experimental/memory>encabezado. Algunos de los cambios relevantes para soportar shared_ptrmatrices son:
- La definición del tipo de miembro element_typecambia
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- Miembro operator[]agregado
element_type& operator[](ptrdiff_t i) const noexcept;
- A diferencia de la unique_ptrespecialización parcial para matrices, tanto shared_ptr<T[]>y shared_ptr<T[N]>será válida y ambos se traducirá en delete[]ser llamado en la matriz administrada de objetos.
template<class Y> explicit shared_ptr(Y* p);
Requiere : Ydebe ser un tipo completo. La expresión delete[] p, cuando Tes un tipo de matriz o delete p, cuando Tno es un tipo de matriz, estará bien formada, tendrá un comportamiento bien definido y no arrojará excepciones. Cuando Tes U[N], Y(*)[N]será convertible a T*; cuando Tes U[], Y(*)[]será convertible a T*; de lo contrario, Y*será convertible a T*.
std::vector. Tendría que tener cuidado de pasar la matriz usando referencias para no hacer copias de ella. La sintaxis para acceder a los datos es más limpia que shared_ptr, y cambiar su tamaño es muy fácil. Y obtienes toda la bondad STL si alguna vez la quieres.