Correctamente la destrucción de punteros en un std::map

Tengo un mapa declarado como

std::map<std::string, Texture*> textureMap;

que yo uso para la vinculación de la ruta de acceso a un archivo de textura la textura actual para que yo pueda hacer referencia a la textura por el camino sin la carga de la misma textura a un montón de veces para individuales de los sprites. Lo que no sé cómo hacer es destruir apropiadamente las texturas en el destructor de la clase ResourceManager (donde el mapa es).

Pensé en utilizar un bucle con un iterador como este:

ResourceManager::~ResourceManager()
{
    for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
    {
        delete (*itr);
    }
}

Pero que no funciona, dice eliminar espera un puntero. Es bastante tarde así que seguramente me estoy perdiendo algo obvio, pero yo quería conseguir este trabajo antes de acostarse. Así que estoy cerca o estoy totalmente en la dirección equivocada con esto?

InformationsquelleAutor Mike | 2013-11-14

3 Kommentare

  1. 42

    Tan lejos como su código de ejemplo se va, usted necesita para hacer esto dentro del bucle:

    delete itr->second;

    El mapa tiene dos elementos y que usted necesita para eliminar la segunda. En su caso, itr->first es un std::string y itr->second es un Texture*.

    Si necesita eliminar una entrada en particular, se podría hacer algo como esto:

    std::map<std::string, Texture*>::iterator itr = textureMap.find("some/path.png");
    if (itr != textureMap.end())
    {
        //found it - delete it
        delete itr->second;
        textureMap.erase(itr);
    }

    Usted tiene que asegurarse de que la entrada existe en el mapa de lo contrario puede obtener una excepción al intentar eliminar la textura puntero.

    Una alternativa podría ser la utilización de std::shared_ptr en lugar de un puntero sin formato, entonces usted podría utilizar una sintaxis simple para quitar un elemento del mapa y vamos a la std::shared_ptr manejar la eliminación del objeto subyacente cuando sea apropiado. De esa manera, usted puede utilizar erase() con un argumento clave, así:

    //map using shared_ptr
    std::map<std::string, std::shared_ptr<Texture>> textureMap;
    
    //... delete an entry ...
    textureMap.erase("some/path.png");

    Que hacer dos cosas:

    • Eliminar la entrada de la mapa, si es que existe
    • Si no hay otras referencias a la Texture*, el objeto será eliminado

    Con el fin de utilizar std::shared_ptr necesitará un reciente C++11 compilador, o Boost.

    • Impresionante. ¿Tú también tienes que hacerlo cuando explícitamente se indica qué valor en el mapa está eliminado? Sentido delete textureMap["some/path.png"] trabajo o tienes que hacer delete textureMap["some/path.png"].second así?
    • He actualizado mi respuesta…
    • En lugar de eliminar los elementos uno por uno, utilizando iterador, podemos utilizar el método clear() para eliminar los elementos de una sola vez. De todos modos, tenemos que eliminar la Textura de los punteros, uno por uno.
    • Usted puede hacer «eliminar textureMap[«algunos/ruta de acceso.png»]» para eliminar el objeto, pero recuerda que la clave seguirá mapa a esa dirección por lo que tendrá que hacer algo acerca de eso también.
    • Yo sé lo que quieres decir, pero creo que su uso de la palabra «eliminar» puede confundir a algunos.
    • No usar delete itr->second; en el bucle de invalidar los iteradores?
    • No, ya que no borra el iterador de la misma, sólo se elimina la cosa que el iterador puntos. Se trata de hacer el eliminar en un Texture*.
    • Lo que si hemos duplicado los punteros ? Que esto todavía funciona, entonces ?

  2. 1

    Usted no está usando la herramienta correcta para el trabajo.

    Punteros no debe «propio» de los datos.

    Uso boost::ptr_map<std::string, Textura> lugar.

    • (o en C++11 std::map<std::string, std::unique_ptr<Texture>> si prefieres deben permanecer Estándar)
    • Tan pronto como crear aplicaciones dinámicas, punteros, será el propietario de los datos. Usted puede incluso evitar que.
    • los punteros no debe propios datos.
  3. 1

    La respuesta no solucionar completamente el problema de bucle. Al menos Coverty (TM) no permite borrar el iterador dentro del bucle, y todavía lo utilizan para continuar el bucle. De todos modos, después de borrar la memoria, llamar a clear() en el mapa debe hacer el resto:

    ResourceManager::~ResourceManager()
    {
        for(std::map<std::string, Texture*>::iterator itr = textureMap.begin(); itr != textureMap.end(); itr++)
        {
            delete (itr->second);
        }
        textureMap.clear();
    }
    • textureMap.clear(); es obsoleta porque la textureMap destructor lo hará automáticamente.
    • gracias, tiene sentido!

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea