Почему это обновление карты в векторе <map <int, int >> не выполняется? - PullRequest
1 голос
/ 14 мая 2019

У меня есть структура данных, представленная вектором карт, все из которых имеют одинаковый тип шаблона.Вставка и чтение работает нормально - однако по какой-то причине обновления ничего не делают.Я попробовал методы, описанные здесь , и они отлично работают - если я просто использую саму карту.Однако, когда карта находится в векторе, элемент найден, но не обновлен.Ниже я привел минимальный пример.

#include <iostream>
#include <map>
#include <vector>
#include <optional>

std::vector<std::map<int, int>> vec = std::vector<std::map<int, int>>();

void insert_or_update( int key, int value ) {
    for ( std::map<int, int> map: vec ) {
        auto location = map.find( key );
        if ( location != map.end()) {
            location->second = value;
            std::cout << "This should update the value, but doesn't" << std::endl;
            return;
        }
    }

    // Insert, if no map currently contains the key
    std::cout << "This value is new" << std::endl;
    vec.back().insert( {key, value} );
}

int get_key( int key ) {
    for ( std::map<int, int> map: vec ) {
        auto location = map.find( key );
        if ( location != map.end()) {
            return location->second;
        }
    }

    std::cout << "This value doesn't exist yet" << std::endl;
    return 0;
}

int main()
{
   std::map<int, int> map = std::map<int, int>();
   vec.push_back( map ); 
   std::cout << get_key(3) << std::endl;
   insert_or_update(3, 3);
   std::cout << get_key(3) << std::endl;
   insert_or_update(3, 5);
   std::cout << get_key(3) << std::endl;
   std::cout << "Update in list failed, do it manually..." << std::endl;
   auto location = map.find( 3 );
   location->second = 5;
   std::cout << location->second << std::endl;

   return 0;
}

Итак, мои вопросы:

  1. Почему это не удается?Я уверен, что это какая-то логика указателя, которую я не понимаю.
  2. Что мне нужно изменить, чтобы она работала?

Ответы [ 2 ]

3 голосов
/ 14 мая 2019

Ваша функция insert_or_update делает копию vec в цикле for:

for ( std::map<int, int> map: vec ) {
    auto location = map.find( key );
    if ( location != map.end()) {
        location->second = value;
        std::cout << "This should update the value, but doesn't" << std::endl;
        return;
    }
}

Если вы хотите изменить vec, вам нужна ссылка вместо копии:

for ( std::map<int, int> & map: vec ) {
    //...
}
3 голосов
/ 14 мая 2019

Потому что эта строка:

for ( std::map<int, int> map: vec ) {

Перечисляет каждый элемент в vec по значению . Это делает копию карты на каждой итерации цикла for. Следовательно, вы вставляете новое значение в копию, а не в элемент, который фактически находится в векторе. Это, вероятно, то, что вы хотите - перечислите элементы по ссылке :

for ( std::map<int, int>& map: vec ) {

Или просто:

for ( auto& map: vec ) {

Сделайте то же самое для той же строки в get_key

...