76

我有一个如下map命名:valueMap

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.
}

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

4

6 回答 6

101

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")->second;"string"

于 2012-05-22T09:59:21.247 回答
30

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

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

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

于 2014-01-13T07:12:11.337 回答
2

Steve Jessop回答很好地解释了为什么你不能在. Gabe Rainbow 的回答提出了一个不错的选择。我只想提供一些关于如何使用的示例代码。因此,这是您的增强示例:std::map::operator[]const std::map 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 键“强”

Ideone 上的代码

于 2019-03-08T16:02:11.173 回答
1

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

于 2019-10-27T20:14:12.973 回答
0

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

好吧,您可以将其作为参考传递。标准参考包装器

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"] );
}

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

于 2019-03-08T16:36:34.903 回答
0

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

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;
于 2021-05-09T05:19:59.347 回答