Доступ к картам С++ отбрасывает квалификаторы (const)
В следующем коде говорится, что передача карты как const
в метод operator[]
отбрасывает квалификаторы:
#include <iostream>
#include <map>
#include <string>
using namespace std;
class MapWrapper {
public:
const int &get_value(const int &key) const {
return _map[key];
}
private:
map<int, int> _map;
};
int main() {
MapWrapper mw;
cout << mw.get_value(42) << endl;
return 0;
}
Это из-за возможного распределения, которое происходит на карте доступа? Невозможно ли объявлять функции с доступом к карте const?
MapWrapper.cpp:10: error: passing ‘const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >]’ discards qualifiers
Ответы
Ответ 1
std::map
operator []
не объявляется как const
и не может быть вызван его поведением:
Т & оператор [] (константный ключ и клавиша)
Возвращает ссылку на значение, которое отображается на ключ, эквивалентный ключу, выполняя вставку, если такой ключ еще не существует.
В результате ваша функция не может быть объявлена const
и использовать карту operator[]
.
std::map
find()
функция позволяет вам искать ключ без изменения карты.
find()
возвращает iterator
или const_iterator
в std::pair
, содержащий как ключ (.first
), так и значение (.second
).
В С++ 11 вы также можете использовать at()
для std::map
. Если элемент не существует, функция генерирует исключение std::out_of_range
, в отличие от operator []
.
Ответ 2
Вы не можете использовать оператор [] на карте, которая является константой, поскольку этот метод не является константой, поскольку он позволяет вам изменять карту (вы можете назначить _map [key]). Вместо этого попробуйте использовать метод find.
Ответ 3
Так как operator[]
не имеет перегрузки, связанной с const, он не может быть безопасно использован в функции, связанной с константой. Вероятно, это связано с тем, что текущая перегрузка была построена с целью как возврата, так и установки значений ключа.
Вместо этого вы можете использовать:
VALUE = map.find(KEY)->second;
или, в С++ 11, вы можете использовать оператор at()
:
VALUE = map.at(KEY);
Ответ 4
Некоторые новые версии заголовков GCC (4.1 и 4.2 на моей машине) имеют нестандартные функции-члены map:: at(), которые объявляются как const и throw std:: out_of_range, если ключ отсутствует на карте.
const mapped_type& at(const key_type& __k) const
Из ссылки в комментарии функции, кажется, что это было предложено как новая функция-член в стандартной библиотеке.
Ответ 5
Во-первых, вы не должны использовать символы, начинающиеся с _, потому что они зарезервированы для записи языка/компилятора. Было бы очень легко для _map быть синтаксической ошибкой на компиляторе кого-то, и вам некого было бы винить, кроме вас самих.
Если вы хотите использовать символ подчеркивания, поместите его в конец, а не в начало. Вероятно, вы сделали эту ошибку, потому что видели какой-то код Microsoft. Помните, что они пишут свой собственный компилятор, чтобы они могли уйти от него. Тем не менее, это плохая идея.
оператор [] не только возвращает ссылку, но и фактически создает запись на карте. Таким образом, вы не просто получаете сопоставление, если его нет, вы его создаете. Это не то, что вы намеревались.