C ++ карта доступа отбрасывает квалификаторы (const) - PullRequest
101 голосов
/ 04 ноября 2008

Следующий код говорит, что передача карты как 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 ]

140 голосов
/ 04 ноября 2008

std::map operator [] не объявлено как const и не может быть связано с его поведением:

T & operator [] (const Key & key)

Возвращает ссылку на значение, сопоставленное ключу, эквивалентному ключу, и выполняет вставку, если такой ключ еще не существует.

В результате ваша функция не может быть объявлена ​​const и использовать карту operator[].

std::map Функция find() позволяет искать ключ без изменения карты.

find() возвращает iterator или const_iterator для std::pair, содержащего как ключ (.first), так и значение (.second) .

В C ++ 11 вы также можете использовать at() для std::map. Если элемент не существует, функция выдает исключение std::out_of_range, в отличие от operator [].

10 голосов
/ 04 ноября 2008

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

9 голосов
/ 24 января 2014

Поскольку operator[] не имеет перегрузки, удовлетворяющей const, его нельзя безопасно использовать в функции, удовлетворяющей const. Вероятно, это связано с тем, что текущая перегрузка была создана с целью возврата и установки значений ключа.

Вместо этого вы можете использовать:

VALUE = map.find(KEY)->second;

или, в C ++ 11, вы можете использовать оператор at():

VALUE = map.at(KEY);
7 голосов
/ 04 ноября 2008

Некоторые более новые версии заголовков GCC (4.1 и 4.2 на моем компьютере) имеют нестандартные функции-члены map :: at (), которые объявлены как const и throw std :: out_of_range, если ключ отсутствует в карте.

const mapped_type& at(const key_type& __k) const

Из ссылки в комментарии функции видно, что это было предложено в качестве новой функции-члена в стандартной библиотеке.

0 голосов
/ 19 марта 2010

Во-первых, вы не должны использовать символы, начинающиеся с _, потому что они зарезервированы для автора реализации языка / компилятора. _Map очень легко может быть ошибкой синтаксиса чьего-либо компилятора, и вам некого будет винить, кроме себя.

Если вы хотите использовать подчеркивание, поставьте его в конце, а не в начале. Вы, вероятно, допустили эту ошибку, потому что видели код Microsoft, делающий это. Помните, что они пишут свой собственный компилятор, так что они могут сойти с рук. Несмотря на это, это плохая идея.

оператор [] не только возвращает ссылку, он фактически создает запись на карте. Таким образом, вы не просто получаете отображение, если его нет, вы его создаете. Это не то, что вы намеревались.

...