Pergunta

Suponha que eu tenho um hash_map e um código como

// i is an iterator
i = hash_map.erase(i)

STL do Mas GCC não retornar iterador em apagar, mas um vazio. Agora é um código como

hash_map.erase(i++)

seguro (ou seja, não invalida o iterador ou faz qualquer outra coisa inesperados ou desagradáveis)? Por favor note que este é um hash_map.

Foi útil?

Solução

Sim, isso é seguro, porque o valor de i terá sido definido para o valor seguinte, antes que o valor atual é apagada.

De acordo com a SGI documentação sobre recipientes com hash invalidação não ocorre por falta elementos -erased, nem mesmo para redimensionar (não há nenhuma palavra sobre se inserções causar redimensionamento, de modo que ter cuidado admito que como uma possibilidade) --- mas neste último caso, a ordem de iteração será alterado. Mas isto não se aplica aqui, a menos que você sair do seu caminho para redimensionar o recipiente durante a travessia ou algo assim. : -)

Outras dicas

Você pode encapsular apagar a fornecer a mesma interface para todos os recipientes que você usa:

namespace detail {
template<typename Container, typename R>
struct SelectErase {
  // by default, assume the next iterator is returned
  template<typename Iterator>
  Iterator erase(Container& c, Iterator where) {
    return c.erase(where);
  }
};
// specialize on return type void
template<typename Container>
struct SelectErase<Container, void> {
  template<typename Iterator>
  Iterator erase(Container& c, Iterator where) {
    Iterator next (where);
    ++next;
    c.erase(where);
    return next;
  }
};

template<typename I, typename Container, typename R>
SelectErase<Container,R> select_erase(R (Container::*)(I)) {
  return SelectErase<Container,R>();
}
} // namespace detail

template<typename Container, typename Iterator>
Iterator erase(Container& container, Iterator where) {
  return detail::select_erase<Iterator>(&Container::erase).erase(container, where);
}

Isso exige tanto:

  1. c.erase retorna o iterador para o próximo item. Isto é como vetor, deque, e lista de trabalho.
  2. c.erase retorna void e não invalida a próxima iteração. Isto é como mapa, conjunto, e (não-stdlib) trabalho hash_map.

O ódio à chuva sobre o desfile, mas eu não acho que você propõe é seguro.

i ++ é o operador de pós-incremento, o que significa que é incrementado após a chamada para apagar. Mas invalida apagar todos os iteradores que apontam para o elemento que está sendo apagado. Então, no momento i é incrementado não é válida.

Se você tiver sorte, pode funcionar corretamente por acidente até que um dia ele faz não mais.

Tanto quanto eu estou ciente que não há maneira de contornar isso, mas algo como:

// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top