26 votos

¿Puede utilizar un shared_ptr para RAII de matrices de estilo C?

Estoy trabajando en una sección de código que tiene muchos posibles puntos de falla que causa a la salida de la función temprano. Las bibliotecas estoy interactuando con exigir que el C-estilo de los arrays se pasan a las funciones. Así, 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.
}

Yo quería usar unique_ptr, pero mi compilador actual no lo soporta y el número de referencia sobrecarga en realidad no importa en este caso.

Me pregunto si alguien tiene alguna idea sobre esta práctica cuando se interactúa con el código heredado.

ACTUALIZACIÓN me olvidé por completo acerca de la shared_ptr llamando delete en lugar de delete []. Acabo de ver no hay pérdidas de memoria y decidió ir con ella. Ni siquiera creo que el uso de un vector. Desde que he sido adentrarse en la nueva (para mí) de C++ últimamente estoy pensando que tengo un caso de "Si la única herramienta que tienes es un martillo, todo parece un clavo." síndrome de down. Gracias por los comentarios.

UPDATE2 pensé que había que cambiar la pregunta y dar una respuesta para que sea un poco más valiosa a alguien a cometer el mismo error que yo. Aunque hay alternativas como scoped_array, shared_array y vector, se puede utilizar un shared_ptr para administrar el alcance de una matriz (pero después de esto no tengo idea de por qué me quieren):

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.
    }

27voto

Jon Benedicto Puntos 7020

No use shared_ptr o scoped_ptr para mantener los punteros a la asignación dinámica de las matrices. shared_ptr y scoped_ptr uso delete ptr; a de limpieza cuando el puntero se deja de hacer referencia/sale del ámbito, que invoca un comportamiento indefinido en una asignación dinámica de la matriz. En su lugar, utilice shared_array o scoped_array, que usar correctamente delete[] ptr; cuando destruir.

Para responder a su pregunta, si usted no la va a pasar el puntero inteligente alrededor, uso scoped_array, ya que tiene menos sobrecarga de shared_array.

Como alternativa, utilice std::vector como el almacenamiento de matrices (vectores tienen garantizada la asignación de memoria contigua).

15voto

Nemanja Trifunovic Puntos 17239

Uso boost::scoped_array , o mejor aún std::vector si se trata de una matriz.

7voto

Justin Ardini Puntos 6273

Recomiendo utilizar un std::vector . Elementos de vectors se asignan en el montón y se eliminarán cuando el vector sale de alcance, donde quiera que salga de la función.

Para pasar un vector código heredado que requieren matrices de estilo C, simplemente pasar &vectorName[0] . Los elementos están garantizados para ser contiguos en memoria.

5voto

Nikolai N Fetissov Puntos 52093

Hay boost::scoped_ptr para esto.

3voto

jpalecek Puntos 31928

Esto

shared_ptr<char*> raiiArray(new char[arrayLength]);

no es una buena práctica, pero causa comportamiento indefinido, como asignar con operador new[] , pero shared_ptr utiliza operator delete para liberar la memoria. Es lo correcto usar boost::shared_array o agregar un deleter personalizado.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X