2012-01-06 1 views
8

Nel mio file di intestazione ho incluso la std :: map e uso lo spazio dei nomi appropriato.
Uno dei miei soci è:Errore di compilazione tramite iteratori di mappe

map<unsigned int, double> pT_Spam; 

E nel mio file cpp tento di fare qualcosa che ho fatto spesso da qualche tempo:

for(map<unsigned int, double>::iterator it=pT_Spam.begin() ; it!=pT_Spam.end() ; it++) {/*code*/} 

Quanto sopra è anche menzionata in uno gli esempi di utilizzo di std :: map su cplusplus.com. Anche se ho fatto praticamente lo stesso in altre parti del codice che causano errori di compilazione, in questa particolare linea ottengo il seguente errore da Cygwin:

error: conversion from `std::_Rb_tree_const_iterator<std::pair<const unsigned int, double> >' to non-scalar type `std::_Rb_tree_iterator<std::pair<const unsigned int, double> >' requested 

Che sembra piuttosto strano. Qualche idea di cosa potrebbe essere sbagliato? (La mia intestazione è, ovviamente, inclusa nel mio cpp)

+0

Si sta lamentando che l'iteratore restituito da begin() è un const_iterator, ma lo si sta assegnando a un iteratore. Ma non sono sicuro del perché, anche questo mi sembra giusto. Che compilatore è questo? – Joe

+0

[begin()] (http://cplusplus.com/reference/stl/map/begin/) sembra essere in grado di restituire anche iteratori non const. Uso il g ++ di Cygwin su Windows. – jathanasiou

risposta

16

Sembrerebbe che allo scopo questo ciclo esista, la mappa sia const. Ad esempio, il ciclo in un metodo di classe dichiarato const, in questo modo?

void method() const // const method 
{ 
    // Do stuff. 
} 

o passato come argomento const, come questo?

void function(const map<unsigned int, double>& pT_Spam) 
{ 
    // Do stuff. 
} 

Se lo è, è necessario utilizzare gli iteratori const:

for(map<unsigned int, double>::const_iterator it=pT_Spam.begin() ; it!=pT_Spam.end() ; it++) 
{ 
    /*code*/ 
} 

Oppure, se si sta utilizzando C++ 11, quindi si dovrebbe utilizzare la parola chiave auto:

for(auto it=pT_Spam.begin() ; it!=pT_Spam.end(); it++) 
{ 
    /*code*/ 
} 

Dato che nel caso in cui hai mostrato devi usare gli iteratori const, non puoi usarli per modificare la mappa oi dati al suo interno. Questa è la correttezza costante, ed è una buona cosa :).

+2

-.25 per l'utilizzo automatico in modo tale da uccidere i gattini. ;) –

+1

Un'alternativa è contrassegnare il membro come ['mutable'] (http://www.highprogrammer.com/alan/rants/mutable.html). Ma non dirlo a nessuno che te l'ho detto :-) –

+0

Il metodo che esegue il ciclo è effettivamente const, e questo mi fa capire perché anche la mappa è const nel suo ambito. Considerando che non ho bisogno di modificarlo in questo metodo, gli iteratori di const sembrano la risposta. – jathanasiou

2

È necessario utilizzare const_iterators per le mappe, quindi dovrebbe essere:

for(map<unsigned int, double>::const_iterator it = \\and so on 

Edit: Come sottolineato quanto sopra è giusto, ma per completamente errati motivi (le mappe hanno iteratori non costanti, cosa stavo pensando esattamente? non so). Molto probabilmente la tua mappa è definita come const (come indicato in un'altra risposta).

+1

Non causerà problemi quando si altera il loro valore (it ++)? Inoltre, ho utilizzato ripetuti iteratori per loop simili finora e non ho mai avuto problemi. – jathanasiou

+2

Ehm, cosa? la mappa ha iteratori non costanti. –

+1

@JohnAthanasiou: Un const-iterator mutabile non è lo stesso di un iteratore const non const. Si pensi 'T const *' vs 'T * const'. –

3

Bene, l'errore indica che stai provando a trasmettere un const_iterator a un iteratore. Tu dici che pT_Spam è un membro. È un membro di un oggetto const? Se lo è, begin() e end() restituiranno const_iterators.

+0

Non sono sicuro di essere onesto, è un membro privato dichiarato della mia classe 'nbclassifier', mentre il metodo che esegue il ciclo è anche membro di quella classe. – jathanasiou

+0

Un'alternativa è contrassegnare il membro come ['mutable'] (http://www.highprogrammer.com/alan/rants/mutable.html). Ma non dirlo a nessuno che te l'ho detto :-) –

+0

Const arriva da qualche parte. Se la variabile membro non è dichiarata const e se il metodo non è dichiarato const, allora forse il metodo viene chiamato su un oggetto const (che renderebbe la variabile membro implicitely const). L'errore del compilatore viene fornito con uno stack di chiamate? EDIT: wait, dovrebbe essere un metodo const se viene chiamato su un oggetto const. –

1

per (mappa :: iterator it = pT_Spam.begin();! It = pT_Spam.end(), ma ++)

chage al

per (mappa :: const_iterator it = pT_Spam. begin(); it! = pT_Spam.end(); it ++)

Poiché punta al valore costante, l'iteratore deve essere anche di tipo const.