【问题标题】:Why does this update to a map in a vector<map<int, int>> fail?为什么对 vector<map<int, int>> 中的地图的更新失败?
【发布时间】:2019-05-14 09:10:31
【问题描述】:

我有一个由地图向量表示的数据结构,所有地图都具有相同的模板类型。插入和读取工作正常 - 但是,出于某种原因,更新什么也不做。我尝试了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. 我必须进行哪些更改才能使其正常工作?

【问题讨论】:

  • for ( std::map&lt;int, int&gt; map: vec ) { 中,您正在迭代地图的副本。将其替换为 for ( std::map&lt;int, int&gt;&amp; map: vec ) {

标签: c++ stl c++17


【解决方案1】:

因为这一行:

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

枚举vec中的每个元素按值。它在 for 循环的每次迭代中制作地图的副本。因此,您将新值插入到副本中,而不是实际在向量中的项中。这可能是您想要的 - 通过引用列举项目:

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

或者简单地说:

for ( auto& map: vec ) {

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

【讨论】:

    【解决方案2】:

    您的函数insert_or_updatefor 循环中复制vec

    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 ) {
        //...
    }
    

    【讨论】:

    • 啊,这很有道理。我仍然需要更好地掌握 C++。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2010-09-24
    • 1970-01-01
    • 2023-01-20
    • 1970-01-01
    • 2013-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    相关资源
    最近更新 更多