2012-11-29 13 views
5

ho qualche codice che sto aggiornando a C++ 11 utilizzando gcc 4.7 (da 3,1)std :: multiset :: iterator = NULL non più valido?

Ho un multiset definito come un membro privato di una classe:

multiset <Object*, objectcomp> objects_; 

Nel codice è un segmento che assomiglia a questo (p_q è una coppia di iteratori multiset, dispiace per quella linea brutto, non vedo l'ora di sostituire quello con auto, haha):

void Terrain::removeObject(Object* obj){ 
    pair<multiset<Object*, objectcomp>::iterator, multiset<Object*, objectcomp>::iterator> p_q; 
    multiset<Object*, objectcomp>::iterator p,q; 
    q = NULL; 
    p_q = objects_.equal_range(obj); 
    for(p = p_q.first; p != p_q.second; p++){ 
     if(*p == obj) {q=p; break;} 
    } 
    if(q!=NULL){ 
     ... do stuff based on q no longer being null 
    } 
} 

questo non sarà più a compilare. Non puoi più impostare gli iteratori su null? Qual è l'alternativa? (nullptr non funziona neanche)

+9

Questo era ** mai ** valido. – ildjarn

+1

oh, beh questo è imbarazzante, haha ​​ –

risposta

7

Non è mai stato legale impostare iteratori su NULL. Potresti aver avuto fortuna perché la tua particolare implementazione ha utilizzato puntatori come iteratori per quel tipo, ma era ancora illegale.

La risposta giusta è:

q = objects_.end(); 

Oppure, in alcuni casi:

q = multiset<Object*, objectcomp>::iterator(); 
+1

Qualcuno sa perché il mio primo blocco di codice non viene visualizzato come codice? – abarnert

+0

La copia e incolla non funzionava ... ma rimuovere '_', quindi tagliare, quindi incollare, fare ... Stranamente ... – abarnert

+0

Originariamente c'erano spazi non interrotti invece di spazi adeguati; apparentemente SO non conta gli spazi non interrotti come indentazione degli spazi bianchi. – ildjarn

2

È mai possibile impostare un iteratore NULL. Se il codice di cui sopra ha mai funzionato, è stato per puro caso. Data qualsiasi ragionevole implementazione del multiset, è difficile vedere come possa mai essere compilato, per non parlare dell'esecuzione.

Il modo migliore per ottenere un iteratore "da nessuna parte" è utilizzare la fine del contenitore. Sostituire q = NULL con q = objects_.end().

Inoltre, non inserire mai puntatori grezzi in un contenitore; è un invito aperto alle perdite di memoria. Quasi certamente vuoi o multiset<Object,comp> o multiset<shared_ptr<Object>,comp>.

+0

Non ho mai nemmeno sentito parlare di shared_ptr, immagino che lo vedrò. Grazie per i ** puntatori **. –

+0

+1 per il punto su non utilizzare i puntatori grezzi in un contenitore. @EricB: dai anche un'occhiata a [boost :: ptr_container] (http://www.boost.org/doc/libs/1_52_0/libs/ptr_container/doc/ptr_container.html), che consente al contenitore di agli oggetti Se gli oggetti non hanno bisogno di rimanere in vita dopo che hanno lasciato il container (o hanno solo bisogno di rimanere in vita fino alla fine dell'ambito corrente se hanno lasciato il contenitore), potrebbe essere molto più semplice (e più efficiente) di un contenitore di puntatori condivisi. – abarnert

Problemi correlati