Доступ к карте C ++ отбрасывает квалификаторы (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
Решение
std::map
's operator []
не объявляется как const
, и не может быть связано с его поведением:
T& operator[] (постоянный ключ и клавиша)
Возвращает ссылку на значение, которое сопоставлено с ключом, эквивалентным key, выполняя вставку, если такой ключ еще не существует.
В результате ваша функция не может быть объявлена const
, и используйте карту operator[]
.
std::map
's find()
функция позволяет вам искать ключ без изменения карты.
find()
возвращает iterator
, или const_iterator
к std::pair
содержащий оба ключа (.first
) и значение (.second
).
В C ++ 11 вы также могли бы использовать at()
для std::map
.Если элемент не существует, функция выдает std::out_of_range
исключение, в отличие от operator []
.
Другие советы
Вы не можете использовать operator[]
на карте , которая есть const
поскольку этот метод не является const
поскольку это позволяет вам изменять карту (вы можете назначить _map[key]
).Попробуйте использовать find
метод вместо этого.
С тех пор как operator[]
не имеет постоянной перегрузки, ее нельзя безопасно использовать в постоянной функции.Вероятно, это связано с тем, что текущая перегрузка была создана с целью как возврата, так и установки значений ключа.
Вместо этого вы можете использовать:
VALUE = map.find(KEY)->second;
или, в C ++ 11, вы можете использовать at()
оператор:
VALUE = map.at(KEY);
Некоторые более новые версии заголовков GCC (4.1 и 4.2 на моей машине) имеют нестандартные функции-члены map::at(), которые объявляются const и выдают std::out_of_range, если ключа нет в map.
const mapped_type& at(const key_type& __k) const
Из ссылки в комментарии к функции следует, что это было предложено в качестве новой функции-члена в стандартной библиотеке.
Во-первых, вы не должны использовать символы, начинающиеся с _, потому что они зарезервированы для разработчика языковой реализации / компилятора.Для _map было бы очень легко оказаться синтаксической ошибкой в чьем-то компиляторе, и вам некого было бы винить, кроме себя.
Если вы хотите использовать символ подчеркивания, поставьте его в конце, а не в начале.Вероятно, вы допустили эту ошибку, потому что видели, как какой-то код Microsoft делает это.Помните, что они пишут свой собственный компилятор, так что, возможно, им это сойдет с рук.Тем не менее, это плохая идея.
operator [] не только возвращает ссылку, но и фактически создает запись на карте.Таким образом, вы не просто получаете сопоставление, если его нет, вы его создаете.Это не то, что ты хотел сказать.