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