【问题标题】:How can I get a value from a map?如何从地图中获取值?
【发布时间】:2012-05-28 19:20:22
【问题描述】:

我有一个名为valueMapmap 如下:

typedef std::map<std::string, std::string>MAP;
MAP valueMap;
...
// Entering data.

然后我通过引用将此映射传递给函数:

void function(const MAP &map)
{
  std::string value = map["string"];
  // By doing so I am getting an error.
}

如何从映射中获取值,该值作为对函数的引用传递?

【问题讨论】:

  • 在发布您遇到的错误时,您应该始终在问题中包含实际错误。

标签: c++ dictionary stdmap


【解决方案1】:

std::map::operator[] 是一个非常量成员函数,并且您有一个 const 引用。

您要么需要更改function 的签名,要么:

MAP::const_iterator pos = map.find("string");
if (pos == map.end()) {
    //handle the error
} else {
    std::string value = pos->second;
    ...
}

operator[] 通过向映射添加默认构造值并返回对它的引用来处理错误。当你只有一个 const 引用时,这是没有用的,所以你需要做一些不同的事情。

可以忽略这种可能性并写string value = map.find("string")-&gt;second;,如果你的程序逻辑以某种方式保证"string"已经是一个键。明显的问题是,如果你错了,你就会得到未定义的行为。

【讨论】:

  • 如果您的编译器还不支持auto,请使用MAP::const_iterator 而不是auto
  • 应该是std::string value = pos-&gt;second;还是const std::string&amp; value = pos-&gt;second;
  • @smerlin:好点,已修复。提问者是否真的需要该值的副本,或者是否可以使用 const 引用,取决于未显示的代码。所以我决定不打扰它:-)
【解决方案2】:

map.at("key") 如果缺少 key 则抛出异常。

如果 k 不匹配容器中任何元素的键,则 函数抛出 out_of_range 异常。

http://www.cplusplus.com/reference/map/map/at/

【讨论】:

    【解决方案3】:

    Steve Jessopanswer 很好地解释了为什么不能在const std::map 上使用std::map::operator[]Gabe Rainbow 的answer 提出了一个不错的选择。我只想提供一些关于如何使用map::at() 的示例代码。因此,这是您的function() 的增强示例:

    void function(const MAP &map, const std::string &findMe) {
        try {
            const std::string& value = map.at(findMe);
            std::cout << "Value of key \"" << findMe.c_str() << "\": " << value.c_str() << std::endl;
            // TODO: Handle the element found.
        }
        catch (const std::out_of_range&) {
            std::cout << "Key \"" << findMe.c_str() << "\" not found" << std::endl;
            // TODO: Deal with the missing element.
        }
    }
    

    这里是一个例子main()函数:

    int main() {
        MAP valueMap;
        valueMap["string"] = "abc";
        function(valueMap, "string");
        function(valueMap, "strong");
        return 0;
    }
    

    输出:

    键“字符串”的值:abc
    未找到“强”键

    Code on Ideone

    【讨论】:

      【解决方案4】:

      主要问题是 operator[] 用于在映射中插入和读取值,因此它不能是 const。
      如果键不存在,它将创建一个带有默认值的新条目,增加映射的大小,其中将包含一个带有空字符串的新键,在这种特殊情况下,如果键不存在,则作为值还不存在。
      如前所述,在读取地图时应避免使用operator[],并使用map.at(key) 以确保边界检查。这是人们在使用地图时经常犯的最常见错误之一。你应该使用insertat,除非你的代码知道这个事实。查看这篇关于常见错误的讨论Curiously Recurring C++ Bugs at Facebook

      【讨论】:

        【解决方案5】:

        如何从映射中获取值,该值作为对函数的引用传递?

        好吧,您可以将其作为参考传递。 The standard reference wrapper 就是这样。

        typedef std::map<std::string, std::string> MAP;
        // create your map reference type
        using map_ref_t = std::reference_wrapper<MAP>;
        
        // use it 
        void function(map_ref_t map_r)
        {
            // get to the map from inside the
            // std::reference_wrapper
            // see the alternatives behind that link
            MAP & the_map = map_r;
            // take the value from the map
            // by reference
            auto & value_r = the_map["key"];
            // change it, "in place"
            value_r = "new!";
        }
        

        还有测试。

            void test_ref_to_map() {
        
            MAP valueMap;
            valueMap["key"] = "value";
            // pass it by reference
            function(valueMap);
            // check that the value has changed
            assert( "new!" == valueMap["key"] );
        }
        

        我认为这很好而且很简单。享受...

        【讨论】:

          【解决方案6】:

          虽然有点晚了,但我还是会回答,感谢之前对这个问题的回答,我能够伪造这个重用指针和值的类,它创建了两个映射来存储数据,如果有人感兴趣,这里是代码..

          template<class T1, class T2> class Bimap
          {
          std::map<T1, T2*> map1;
          std::map<T2, T1*> map2;
          public:
              void addRow(T1 &t1, T2 &t2){
                  map1.insert(make_pair(t1, &t2));
                  map2.insert(make_pair(t2, &t1));
              }
              T2* findForward(T1 t1){
                  T2* value = map1.find(t1)->second;
                  return value;
              }
              T1* findBackward(T2 t2){
                  T1* value = map2.find(t2)->first;
                  return value;
              }
          };
          

          使用类:

          //Init mapp with int,int
          Bimap<int,int> mapp;
          
          //Add a row(Record) in bimap
          int a = 5;
          int b = 7002;
          mapp.addRow(a, b);
          
          //Print a record
          int *ans= mapp.findForward(a);
          cout<<"Bimap Returned:"<<*ans<<endl;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-05-21
            • 1970-01-01
            • 1970-01-01
            • 2022-11-10
            • 1970-01-01
            • 1970-01-01
            • 2016-04-04
            相关资源
            最近更新 更多