为什么此更新到vector <map <int,int =“” >>中的地图失败?

时间:2019-05-14 09:10:31

标签: c++ stl c++17

我有一个由地图矢量表示的数据结构,所有地图都具有相同的模板类型。插入和读取工作正常-但是,由于某种原因,更新无济于事。我尝试了here中描述的方法,并且它们工作正常-如果我只是使用地图本身。但是,当地图位于向量中时,会找到该元素但未更新。下面,我提供了一个最小的示例。

#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 个答案:

答案 0 :(得分:3)

因为这一行:

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

正在按值枚举vec中的每个元素。在for循环的每次迭代中,它都会复制地图。因此,您要在副本中插入一个新值,而不是向量中实际存在的into项。这可能就是您想要的-通过引用枚举项目

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

或者简单地:

for ( auto& map: vec ) {

get_key中的同一行执行相同操作

答案 1 :(得分:3)

您的函数insert_or_updatevec循环中复制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 ) {
    //...
}