Доступ к карте C ++ отбрасывает квалификаторы (const)

StackOverflow https://stackoverflow.com/questions/262853

  •  06-07-2019
  •  | 
  •  

Вопрос

Следующий код говорит, что передача карты как 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 [] не только возвращает ссылку, но и фактически создает запись на карте.Таким образом, вы не просто получаете сопоставление, если его нет, вы его создаете.Это не то, что ты хотел сказать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top