Как я могу получить значение для ключа от const ref? - PullRequest
0 голосов
/ 03 мая 2018

Почему я не могу получить значение ключа в const ref unordered_map, которое я передал в функцию, но могу для локального unordered_map?

GameObject(const std::unordered_map<int,std::unordered_map<int,int>>& objectParameters){
        if (objectParameters.find(CAPABILITY_TYPE_SPECIE)!=objectParameters.end()) {

 //Following line gives an error:
    auto map2 = objectParameters[CAPABILITY_TYPE_SPECIE];         

//Following line works just fine
            std::unordered_map<int,std::unordered_map<int,int>> objectParameters2;
            auto map = objectParameters2[CAPABILITY_TYPE_SPECIE];

        }

Почему я не могу получить значение из objectParameters? Ошибка, на которую жалуется компилятор:

Нет жизнеспособного перегруженного оператора [] для типа 'const std :: unordered_map> '

РЕДАКТИРОВАТЬ: удаление "const" из типа, кажется, ошибка исчезнет. Это почему ?

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Почему я не могу получить значение из objectParameters?

Поскольку при доступе к элементу карты с помощью оператора [] и ключа не существует, он будет создан. Очевидно, что компилятор не может сделать это, если карта const.

Вы можете попробовать использовать .at(), так как он имеет const перегрузку http://en.cppreference.com/w/cpp/container/map/at

0 голосов
/ 03 мая 2018

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

Вы используете find(), а затем просто отбрасываете результат, почему? Он получает итератор для элемента, если этот элемент существует. Так что не отказывайтесь от этого, используйте его.

auto item = objectParameters.find(CAPABILITY_TYPE_SPECIE);
if (item != objectParameters.end()) {
     auto map2 = item->second;

Хотя, если вы хотите, чтобы map2 был тем же, который уже есть в map1, вышеприведенное также не делает этого. Поскольку auto map2 является копией item->second. Чтобы изменить элемент в map1, нам нужно сделать map2 ссылку:

auto item = objectParameters.find(CAPABILITY_TYPE_SPECIE);
if (item != objectParameters.end()) {
     auto& map2 = item->second;

Что касается вашего редактирования, удаление const для "исправления" таких ошибок - неправильная вещь. Правильность Const важна, и когда вы делаете такое «исправление», это может привести к незначительным ошибкам в вашем коде. Потому что теперь вещи, которые не должны меняться, могут начать неожиданно меняться.

...