2012-01-25 21 views
8
Driver::~Driver() 
{ 
    AutoCritSec acsDriverList(m_csDriverList,true); 
    DRIVERLIST::iterator it = m_DriverList.begin(); 
    for(;it!=m_DriverList.end();it++) 
    { 
     if (it->second == this) 
     { 
      m_DriverList.erase(it); 
      it = m_DriverList.begin(); 
     } 
    } 
} 

Cuando compilo mi programa en visual studio 2003, mi programa se comporta bien. pero cuando hago lo mismo en 2010, a continuación, al cerrar la aplicación yo consiga un cierto error comomap/set iterator no incrementablemap/set iterator no incrementable

Expression:map/set iterator not incrementable 

y cuando pulso ignorar esta me sale

Expression:"standard c++ library out of range" && 0 

¿Alguien tiene alguna idea de lo que es aquí: estoy en deuda con cualquier sugerencia de alguien. Toneladas de agradecimientos y cálidos deseos.

Respuesta

12

Si this es el único elemento de la lista, sobrepasará el final de la lista.

Después de eliminar this de la lista, restablece it = m_DriverList.begin();. Esto esta bien. A continuación, se evalúa la expresión de bucle (i++ de la instrucción for), lo que hace que it avance más allá del final del rango.

Avanzar un iterador más allá del final del contenedor hace que el programa muestre un comportamiento indefinido. Las versiones recientes de Visual C++ detectan útilmente muchos errores de iterador comunes en las compilaciones de depuración de su programa y aumentan las afirmaciones para ayudarlo a resolverlos.

puede resolver el problema eliminando la expresión de bucle y llevarlos a un estado de else:

while (it != m_DriverList.end()) 
{ 
    if (it->second == this) 
    { 
     m_DriverList.erase(it); 
     it = m_DriverList.begin(); 
    } 
    else 
    { 
     ++it; 
    } 
} 

Aunque, reiniciar iteración cada vez que se quita un elemento es más bien un desperdicio. Considere en lugar de utilizar mediante el iterador devuelto por la llamada a erase:

it = m_DriverList.erase(it); 
+0

una buena recomendación de borrado/eliminar. En este caso particular, m_DriverList es aparentemente un contenedor de pares o es un mapa de algún tipo, ya que la prueba está en ello-> segundo. En lugar de std :: remove, requerirá std :: remove_if con una función lambda o de comparación. –

+0

Si el contenedor es un mapa (título de la pregunta, acceso al miembro 'segundo') entonces no creo que se pueda aplicar la expresión * borrar-eliminar *. La idiomática es similar al ciclo while que tiene, pero en lugar de reiniciar la iteración, copia y avanza el iterador y luego borra la posición actual. –

+0

@ DavidRodríguez-dribeas @MarkTaylor: Buena captura; Me distrajo con "Lista" en el nombre de la variable. En C++ 11, 'erase' devuelve el iterador al siguiente elemento (o a uno-pasado-el-final si no hay próximo elemento), y Visual C++ 2010 lo admite. –

6

La expresión correcta de borrado para los contenedores asociativos es el siguiente:

for (auto it = container.begin(); it != container.end() /* not hoisted */; /* no inc. */) 
{ 
    if (delete_condition) 
    { 
     container.erase(it++); 
    } 
    else 
    { 
     ++it; 
    } 
}