C ++ const std :: map ссылка не компилируется - PullRequest
15 голосов
/ 27 марта 2009

Есть ли причина, по которой передача ссылки на std::map в качестве const приводит к разрыву оператора []? Я получаю эту ошибку компилятора (GCC 4.2), когда я использую const:

ошибка: нет совпадения с оператором [] в «Карта [имя]

Вот прототип функции:

void func(const char ch, std::string &str, const std::map<std::string, std::string> &map);

И я должен отметить, что при удалении ключевого слова const перед std::map.

проблем не возникает.

Если меня правильно проинструктировали, оператор [] фактически вставит новую карту в карту, если не найдет ключ, что, конечно, объясняет, почему это происходит, но я не могу себе представить, что это будет когда-либо приемлемым поведением.

Если есть лучший метод, такой как find вместо [], я был бы признателен. Кажется, я тоже не могу заставить работать find ... Я получаю const несоответствующих ошибок итератора.

Ответы [ 5 ]

26 голосов
/ 27 марта 2009

Да, вы не можете использовать operator[]. Используйте find, но обратите внимание, что возвращается const_iterator вместо iterator:

std::map<std::string, std::string>::const_iterator it;
it = map.find(name);
if(it != map.end()) {
    std::string const& data = it->second;
    // ...
}

Это как с указателями. Вы не можете назначить int const* на int*. Кроме того, вы не можете назначить const_iterator на iterator.

7 голосов
/ 27 марта 2009

Когда вы используете оператор [], std :: map ищет элемент с данным ключом. Если он не находит ничего, он создает его. Отсюда и проблема с конст.

Используйте метод поиска, и все будет в порядке.

Не могли бы вы опубликовать код о том, как вы пытаетесь использовать find ()? Правильный путь будет:

if( map.find(name) != map.end() )
{
   //...
}
3 голосов
/ 04 июня 2014

Если вы используете C ++ 11, std :: map :: at должно работать для вас.

Причина, по которой std :: map :: operator [] не работает, в том, что в случае, если искомого ключа не существует на карте, он вставит новый элемент с предоставленный ключ и вернуть ссылку на него (подробности см. по ссылке). Это невозможно на const std :: map.

Однако метод at генерирует исключение, если ключ не существует. При этом, вероятно, будет хорошей идеей проверить наличие ключа с помощью метода std :: map :: find, прежде чем пытаться получить доступ к элементу с помощью метода at.

2 голосов
/ 27 марта 2009

Для ваших "несоответствующих константных ошибок итератора":

find () имеет две перегрузки:

      iterator find ( const key_type& x );
const_iterator find ( const key_type& x ) const;

My думаю, заключается в том, что вы получаете эту ошибку, потому что вы делаете что-то вроде присвоения неконстантного итератора (слева) результату вызова find() для const карта:

iterator<...> myIter /* non-const */ = myConstMap.find(...)

Это может привести к ошибке, хотя, возможно, не той, которую вы видите.

2 голосов
/ 27 марта 2009

Возможно, потому что в std :: map нет оператора const []. Оператор [] добавит искомый элемент, если не найдет его. Поэтому используйте метод find (), если вы хотите искать без возможности добавления.

...