2012-01-06 9 views
8

W moim pliku nagłówkowym umieściłem std :: map i używam odpowiedniej przestrzeni nazw.
Jeden z moich członków jest:Błąd kompilacji przy użyciu iteratorów map

map<unsigned int, double> pT_Spam; 

A w moim pliku .cpp staram się zrobić coś, co robiłem często już od jakiegoś czasu:

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

Powyższe jest nawet wspomniane w jeden z przykładów użycia std :: map na cplusplus.com. Mimo, że zrobili bardzo podobnie w innych częściach kodu, które nie powodują błędy kompilacji, w tej konkretnej linii pojawia się następujący błąd z 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 

co wydaje się dość dziwne. Masz pojęcie, co może być nie tak? (Mój nagłówek jest oczywiście wliczone w .cpp)

+0

Narzeka, że ​​iterator zwrócony przez funkcję begin() to const_iterator, ale przypisujesz go do iteratora. Ale nie jestem pewien dlaczego, to też wygląda na mnie. Jaki to kompilator? – Joe

+0

[begin()] (http://cplusplus.com/reference/stl/map/begin/) wydaje się być zdolny do zwracania także iteratorów niestanowiących stałych. Używam g ++ cygwin w systemie Windows. – jathanasiou

Odpowiedz

16

Wygląda na to, że w zasięgu tej pętli istnieje mapa. Na przykład, czy pętla w klasie jest zadeklarowana jako const, podobnie jak w przypadku?

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

lub przekazany jako argument stały, taki jak ten?

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

Jeśli tak jest, należy użyć const iteratorów:

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

Lub, jeśli używasz C++ 11, wtedy należy użyć słowa kluczowego auto:

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

Ponieważ w przypadku, w którym pokazałeś, że musisz używać stałych iteratorów, nie możesz ich użyć do modyfikacji mapy lub danych w niej. To poprawność const, i to dobrze :).

+2

-.25 za używanie auto w sposób, który zabija kocięta. ;) –

+1

Alternatywą jest oznaczenie członka jako ['zmienny'] (http://www.highprogrammer.com/alan/rants/mutable.html). Ale nie mów nikomu, że ci to powiedziałam :-) –

+0

Metoda uruchamiająca pętlę jest rzeczywiście const, co pozwala mi zrozumieć, dlaczego mapa jest również w swoim zasięgu. Biorąc pod uwagę, że nie muszę go edytować w tej metodzie, iteratory wydają się być odpowiedzią. – jathanasiou

2

Trzeba użyć const_iterators na mapach, więc powinno być:

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

Edit: Jak wskazano wyżej ma rację, ale dla całkowicie złe powody powodów (mapy mają iterators non-const.) Co dokładnie myślałem? Nie wiem). Najprawdopodobniej twoja mapa jest zdefiniowana jako const (jak wskazano w innej odpowiedzi).

+1

Czy nie spowoduje to problemów przy zmianie ich wartości (it ++)? Ponadto używam zwykłych iteratorów do podobnych pętli do tej pory i nigdy nie miałem problemów. – jathanasiou

+2

Um, co? mapa ma nieciągłe iteratory. –

+1

@JohnAthanasiou: Zmienny iterator const nie jest tym samym, co stały iterator const! Pomyśl 'T const *' vs 'T * const'. –

3

Cóż, błąd mówi, że próbujesz rzucić const_iterator do iteratora. Mówisz, że pT_Spam jest członkiem. Czy jest członkiem obiektu const? Jeśli tak, begin() i end() zwrócą const_iterators.

+0

Nie jestem szczery, to deklarowany prywatny członek mojej klasy "nbclassifier", a metoda, która wykonuje pętlę, jest również członkiem tej klasy. – jathanasiou

+0

Alternatywą jest oznaczenie członka jako ['zmienny'] (http://www.highprogrammer.com/alan/rants/mutable.html). Ale nie mów nikomu, że ci to powiedziałam :-) –

+0

Const jest gdzieś. Jeśli zmienna składowa nie jest zadeklarowana jako stała, a metoda nie jest zadeklarowana jako stała, to może wywoływana jest metoda na obiekcie const (co spowodowałoby, że stała składowa stała niejawnie). Czy błąd kompilatora występuje w zestawie wywołań? EDYCJA: czekaj, musiałaby to być metoda const, jeśli jest wywoływana na obiekcie const. –

1

dla (mapa :: iterator it = pT_Spam.begin();! Go = pT_Spam.end(); go ++)

chage go

dla (mapa :: const_iterator it = pT_Spam. begin(); it! = pT_Spam.end(); it ++)

Ponieważ wskazuje na wartość stałą, więc iterator musi być również typu const.