Domanda

Supponiamo che io abbia una hash_map e un codice come

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

Ma l'STL di GCC non restituisce l'iteratore in cancellazione, ma un vuoto. Ora è un codice come

hash_map.erase(i++)

sicuro (cioè non invalida l'iteratore o fa altre cose inaspettate o spiacevoli)? Questa è una hash_map.

È stato utile?

Soluzione

Sì, questo è sicuro, perché il valore di i sarà stato impostato sul valore successivo, prima che il valore corrente venga cancellato.

Secondo la la documentazione SGI sui contenitori con hash non si verifica per elementi con telecamere, nemmeno per il ridimensionamento (non vi è alcuna parola sul fatto che gli inserimenti causino il ridimensionamento, quindi, per essere attento, lo ammetto come una possibilità) --- ma in quest'ultimo caso, l'ordine di iterazione verrà modificato. Ma questo non si applica qui, a meno che non si faccia di tutto per ridimensionare il contenitore durante l'attraversamento o qualcosa del genere. : -)

Altri suggerimenti

Puoi incapsulare la cancellazione per fornire la stessa interfaccia per tutti i contenitori che usi:

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);
}

Ciò richiede:

  1. c.erase restituisce l'iteratore per l'elemento successivo. Ecco come funzionano vector, deque ed list.
  2. c.erase restituisce null e non invalida il successivo iteratore. Ecco come funzionano map, set e hash_map (non stdlib).

Odio far piovere sulla parata, ma non credo che ciò che proponi sia sicuro.

i ++ è l'operatore post-incremento, il che significa che viene incrementato dopo la chiamata per cancellare. Ma cancella invalida tutti gli iteratori che puntano all'elemento che si sta cancellando. Quindi, una volta incrementato, non è più valido.

Se sei fortunato, potrebbe funzionare correttamente per errore fino a quando un giorno non lo farà più.

Per quanto ne so non c'è modo di aggirare questo, ma qualcosa di simile:

// tmp and i are both iterators
tmp = i;
++i;
hash_map.erase(tmp);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top