Validade do iterador, depois de apagar () ligue para std :: set
Pergunta
Apagar a chamada em std :: Definir invalidar iterator? Como fiz abaixo do 5º da última linha ..? Se sim, qual é a melhor maneira de apagar todos os elementos do conjunto
class classA
{
public:
classA(){};
~classA(){};
};
struct structB
{
};
typedef std::set <classA*, structB> SETTYPE;
typedef std::map <int, SETTYPE>MAPTYPE;
int __cdecl wmain (int argc, wchar_t* pArgs[])
{
MAPTYPE mapObj;
/*
...
.. Some Operation Here
...
*/
for (MAPTYPE::iterator itr1=mapObj.begin(); itr1!=mapObj.end(); itr1++)
{
SETTYPE li=(*itr1).second;
for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++)
{
classA *lt=(classA*)(*itr2);
li.erase(itr2);
delete lt; // Does it invalidate Iterator ?
}
}
}
Solução
Como você está aparentemente excluindo todos os elementos do conjunto, você pode fazer:
for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();itr2++)
{
classA *lt=(classA*)(*itr2);
delete lt;
}
li.clear(); // clear the elements
Outras dicas
Do padrão 23.1.2
Os membros da inserção não devem afetar a validade dos iteradores e referências ao contêiner, e os membros apagados devem invalidar apenas iteradores e referências aos elementos apagados.
EDITAR
No seu caso, o ITR2 é invalidado após apagar tão incrementando, causa comportamento indefinido. Nesse caso, você pode seguir o conselho reko_t, em geral, você pode tentar o seguinte:
for (SETTYPE::iterator itr2=li.begin();itr2!=li.end();)
{
classA *lt=(classA*)(*itr2);
li.erase(itr2++);
delete lt;
}
Qual irá incrementar o iterador antes da Removendo seu valor anterior do set.
POR FALAR NISSO. ITR2 não é invalidado por delete lt;
, mas por li.erase(itr2);
O delete está ok.
O problema é que você apaga - e, portanto, invalida - itr2
, mas use -o para iteração de loop.
IAW após a primeira apagar, o ++itr2
tem resultados indefinidos.
O padrão que eu uso nesta situação é o seguinte:
while(itr2 != end())
{
iterator toDelete = itr2;
++itr2; // increment before erasing!
container.erase(toDelete);
}
Alguns ITRTs de STL não padronizados retornam o próximo iterador, para que você possa fazer:
while(itr2 != end())
itr2 = container.erase();
Isso não é portátil, no entanto.
a set<A*,B>
é Estranho, porém - em um implorativo padrão, B seria o comparador.