Tener problemas para eliminar el vector de punteros

Tengo una clase del gestor de la celebración de un vector de punteros a una clase base virtual para permitir una variedad de clases hijas para ser almacenados allí. En el destructor de este gestor de clase, la quiero para hacer un ciclo a través de todos los punteros que tiene y eliminarlos. Sin embargo, he intentado un número de métodos que he encontrado y el programa se bloquea continuamente durante la ejecución.

El código actual que tengo es la que se muestra a continuación:-

for (std::vector<GameState*>::iterator it = gamestates_.begin(); it != gamestates_.end(); ++it){
    delete *it;
    it = gamestates_.erase(it);
}

Una cosa que no he probado aún es el uso de unique_ptr pero estoy seguro de que este debe ser capaz de manejar sin el uso de ellos. Por favor me corrija si estoy equivocado.

Edit: estoy consciente de que debo borrar el vector después de que el bucle pero esto es lo que ha venido después de probar cada método normal de eliminación de los punteros. No parece como el comando eliminar.

6 Kommentare

  1. 5

    Borrar un elemento en el vector invalida el iterador, así que usted no puede continuar la iteración después. En este caso, yo no borrar elementos dentro del bucle; me gustaría borrar el vector después:

    for (auto it = gamestates_.begin(); it != gamestates_.end(); ++it){
        delete *it;
    }
    gamestates_.clear();

    Aunque, si es que esto es el destructor y el vector está a punto de ser destruido, no hay punto de compensación bien.

    Si usted necesita para borrar dentro de un bucle (tal vez debido a que usted sólo desea borrar algunos elementos), entonces usted necesita un poco más de cuidado para mantener el iterador válido:

    for (auto it = gamestates_.begin(); it != gamestates_.end();){ //No ++ here
        if (should_erase(it)) {
            it = gamestates_.erase(it);
        } else {
            ++it;
        }
    }

    Una cosa que no he probado aún es el uso de unique_ptr pero estoy seguro de que este debe ser capaz de manejar sin el uso de ellos. Por favor me corrija si estoy equivocado.

    Si quieres administrar objetos dinámicos por steam, por esto, a continuación, asegúrese de seguir las La regla de Tres: deberá implementar (o eliminar) el constructor de copia y copia-operador de asignación para prevenir «superficial» copiar dejándole con dos vectores que intentar eliminar los objetos mismos. Usted también tendrá que tener cuidado para eliminar los objetos en cualquier otro lugar que se elimina o sustituye. Almacenar punteros inteligentes (o los objetos en sí, si no necesita punteros para el polimorfismo) se hará cargo de todas estas cosas para usted, así que yo siempre recomiendo que.

    Soy consciente de que debo borrar el vector después de que el bucle pero esto es lo que ha venido después de probar cada método normal de eliminación de los punteros. No parece como el comando eliminar.

    La causa más probable es que usted no está siguiendo la Regla de Tres, y son accidentalmente tratando de eliminar los mismos objetos dos veces después de copiar el vector. También es posible que GameState es una clase base y se olvidó de darle un destructor virtual, o que los punteros se han dañado por algún otro código.

    • Esto no parece funcionar bien. Me hizo intentar algo como esto antes, pero nada seemes a trabajar. Es como si no le gusta el comando eliminar. pregunta estúpida: asumo que no es necesario incluir un cierto encabezado para eliminar un puntero.
    • Qué es exactamente «no funciona»?
    • El delete comando está bien, si es un puntero válido. Son accidentalmente copiar el vector y la eliminación de los objetos dos veces? Es GameState una clase base, con los diferentes tipos de objetos reales? Si es así, asegúrese de que tiene un destructor virtual. Si no, ¿por qué almacenar punteros en el primer lugar?
    • Gamestate sostiene virtual de llamadas para init, procesamiento, actualización y cierre, pero cada niño de que también tendrían una serie de sus propias funciones y variables. Ya que yo sólo quiero uno está ejecutando en un momento el gerente llama a init cuando el estado es activo, y se cierran cuando su hecho. El destructor es esencialmente vacío y hay una línea para cerrar el estado activo directamente por encima de la línea que he citado. Espero que estas clases a ser bastante grande por lo que yo estaba tratando de ahorrar espacio de almacenamiento en el montón. tendría que necesitan todavía un destructor virtual en la clase base si que sería esencialmente vacía.
    • Sí, siempre se necesita un destructor virtual para eliminar a través de una base de clase puntero. Asegúrese de que GameState tiene uno, y también asegurarse de que el administrador de una clase no es accidental de copiar el vector.
    • el vector se define (privada a la clase) en el encabezado y añadió a la utilización de push_back, no veo cómo sería copiado en cualquier momento. También, sería un destructor virtual necesita nada partcicular en ella?
    • Pudiera ser copiada si accidentalmente copiar toda la clase manager, usted debe asegurarse de que la clase sigue la Regla de Tres y no copiable, o bien copiable. El uso de unique_ptr automáticamente evitar la copia para usted. El destructor virtual puede estar vacía si no hay nada que hacer para limpiar la base de la clase; sólo tiene que existir.
    • Parece que el problema radica en que no haveing un destructor virtual. Voy a probally cambiar el administrador de un singleton para evitar la copia o, posiblemente, el uso unique_ptr lugar. Es sólo bueno para que no se bloquee cuando se cierra, por ahora, gracias por su ayuda.
    • Los únicos son generalmente considerados como una mala idea, especialmente en C++. Sólo evitar la copia por eliminar el constructor de copia y el operador de asignación: Manager(Manager const&) = delete; void operator=(Manager const&) = delete;
    • Justo lo suficiente, el movimiento de Java va a ser complicado…

  2. 2

    Su iterador se actualiza dos veces en cada bucle:

    it = gamestates_.erase(it);

    y

    it++

    Usted necesita solamente la primera de ellas – que ya se apunta a la «siguiente objeto» en el contenedor.

    • +1 me Pareció un poco injusto que no tenía upvotes, dado que la suya fue la primera respuesta a este señalamiento.
  3. 0

    Borrado de un elemento a partir de su vector invalida el iteradores. Eliminar los objetos puntero por los elementos y, a continuación, clear() el contenido del vector.

  4. 0

    deshacerse de la ++it en su for bucle de cabecera.

    erase ya avances para usted.

    Alternativamente, iterar, eliminar, a continuación, después de la iteración .clear().

  5. 0

    Prefieren utilizar unique_ptr. Usted dice que usted debe ser capaz de manejar sin el uso de ellos como si obtener un puntero inteligente para hacer el trabajo para usted es algún tipo de terrible imposición.

    Están ahí para hacer su vida más fácil, usted no tiene que sentirse culpable por no hacer el trabajo duro a mano.

    Y con su código existente, simplemente no la llame erase. El vector que va a ser destruido de todos modos, ¿verdad? Que va a cuidar de todos los que a sí mismo.

    • «Y con el código existente, sólo que no se llame a borrar. El vector que va a ser destruido de todos modos, ¿verdad? Que va a cuidar de todos los que a sí mismo». A menos que no lo es, en cuyo caso no!
    • Pregunta dice que esto es en el administrador de clase’ destructor, y estoy suponiendo que el vector es un miembro de la sub-objeto.
  6. 0

    El problema es que se están incrementando it dos veces. En primer lugar, cuando usted llame it = .erase(it) que devuelve el siguiente elemento, y luego en el bucle ++i. Usted puede inadvertely saltar por encima de la final y las cosas pueden ir mal, por no hablar de que va a quitar sólo cada segundo elemento de su vector.

    Una solución sencilla es simplemente para no cambiar it en el circuito (no ++it).

    Una mejor manera sería realmente eliminar la matriz desde el extremo del vector, como el borrado de elementos desde el interior del vector introduce un costoso mover de todos los de su seguimiento de los elementos. Su actual algoritmo de trabajo en N^2 tiempo.
    Intentar algo como esto:

    while (!gamestates_.empty()) {
        delete gamestates_.back();
        gamestates_.erase(gamestates_.end()-1);
    }

    Usted también puede simplemente iterar sobre todos los elementos del vector y claro después:

    for (std::vector<GameState*>::iterator it = gamestates_.begin(); it != gamestates_.end(); ++it){
        delete *it;
    }
    gamestates_.clear();

    Tenga en cuenta también, que la clear() operación del vector se realiza también en su destructor. Si el procedimiento de eliminación es parte de algún proceso de destrucción donde gamestates_ es ulimately destruido – usted no tiene que llamar a clear() a todos.

Kommentieren Sie den Artikel

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

Pruebas en línea