c++ - pointer - ¿Se puede usar un shared_ptr para RAII de arreglos de estilo C?
smart pointer c++ (6)
Algunas observaciones para los usuarios de C ++ 11:
Para shared_ptr
, hay en C ++ 11 un eliminador predeterminado para los tipos de arreglos definidos en <memory>
y compatible con las normas (wrt el borrador final), por lo que se puede usar sin eliminaciones de fantasía adicionales para tales casos:
std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>());
unique_ptr
en C ++ 11 tiene una especialización parcial para tratar con new[]
y delete[]
. Pero desafortunadamente no tiene un comportamiento compartido. Debe ser una buena razón por la que no existe tal especialización para shared_ptr
pero no la shared_ptr
, si la conoce, por favor compártala.
Estoy trabajando en una sección de código que tiene muchos puntos de falla posibles que hacen que salga de la función antes. Las bibliotecas con las que estoy interactuando requieren que las matrices de estilo C se pasen a las funciones. Entonces, en lugar de llamar a eliminar en las matrices en cada punto de salida, estoy haciendo esto:
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength]);
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
Quería usar unique_ptr
, pero mi compilador actual no lo admite y la sobrecarga de recuento de referencias realmente no importa en este caso.
Me pregunto si alguien tiene alguna idea sobre esta práctica al interactuar con el código heredado.
ACTUALIZACIÓN Me olvidé por completo de la shared_ptr
delete
shared_ptr
lugar de delete []
. Simplemente no vi ninguna pérdida de memoria y decidí seguir adelante. Ni siquiera pensé en usar un vector. Desde que estoy profundizando en el nuevo (para mí) C ++, últimamente estoy pensando que tengo un caso de "Si la única herramienta que tiene es un martillo, todo parece un clavo". síndrome. Gracias por la respuesta.
ACTUALIZACIÓN2 Me imaginé que cambiaría la pregunta y daría una respuesta para que sea un poco más valioso para alguien que comete el mismo error que yo. Aunque hay alternativas como scoped_array
, shared_array
y vector
, puede usar shared_ptr
para administrar el alcance de una matriz (pero después de esto no tengo idea de por qué querría hacerlo):
template <typename T>
class ArrayDeleter
{
public:
void operator () (T* d) const
{
delete [] d;
}
};
void SomeFunction(int arrayLength)
{
shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>());
pArray = raiiArray.get();
if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }
//etc.
}
Esta
shared_ptr<char*> raiiArray(new char[arrayLength]);
no es una buena práctica, pero causa un comportamiento indefinido, ya que asigna con el operador new[]
, pero shared_ptr
utiliza la operator delete
para liberar la memoria. Lo correcto es usar boost::shared_array
o agregar un eliminador personalizado.
Hay boost::scoped_ptr
para esto.
No use shared_ptr
o scoped_ptr
para mantener los punteros a las matrices asignadas dinámicamente. shared_ptr y scoped_ptr utilizan delete ptr;
para limpiar cuando el puntero ya no está referenciado / queda fuera del alcance, lo que invocó un comportamiento indefinido en una matriz asignada dinámicamente. En su lugar, use shared_array o scoped_array, que utiliza correctamente delete[] ptr;
al destruir
Para responder a su pregunta, si no va a pasar el puntero inteligente, utilice scoped_array
, ya que tiene menos sobrecarga que shared_array
.
Alternativamente, use std::vector
como el almacenamiento de matriz (los vectores han garantizado la asignación de memoria contigua).
Recomiendo altamente usar simplemente un std::vector
. Los elementos de los vectors
se asignan en el montón y se eliminarán cuando el vector
se salga del alcance, siempre que salga de la función.
Para pasar un vector
a un código heredado que requiere arreglos de estilo C, simplemente pase &vectorName[0]
. Los elementos están garantizados para ser contiguos en la memoria.
Use boost::scoped_array
, o incluso mejor std::vector
si está tratando con una matriz.