在字符串的 std::map 中查找编译错误,长

Posted

技术标签:

【中文标题】在字符串的 std::map 中查找编译错误,长【英文标题】:Compilation error in find in a std::map of string, long 【发布时间】:2017-01-07 05:19:09 【问题描述】:

我正在使用 VC++ 开发 Visual Studio 2013。 我有一个 std::map 如下,

std::map<std::string, unsigned int> myMap;

作为类的静态成员。

我通过这样做将值填充到其中,

string key = "value";
std::map<std::string, unsigned int>::iterator it = myMap.find(key);

if(it == myMap.end())
    myMap.insert(std::pair<std::string, unsigned int> (key, 1));
else

    int prev_value = it->second;
    prev_value++;
    myMap.insert(std::pair<std::string, unsigned int> (key, prev_value));

这不编译,我得到这个编译错误,

1   IntelliSense: no suitable user-defined conversion from "std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string, long>>>>" to "std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string, unsigned int>>>>" exists  c:\filename.cpp 15

15 是这一行,

std::map<std::string, unsigned int>::iterator it = myMap.find(key);

还有这个错误,

2   IntelliSense: no operator "==" matches these operands
        operand types are: std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string, unsigned int>>>> == std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<const std::string, long>>>> c:\filename.cpp  17

第 17 行是这样的,

if(it == myMap.end())

有人可以帮我解决这个问题吗?

谢谢

【问题讨论】:

错误消息表明myMap 实际上是std::map&lt;std::string, long&gt; 类型,而不是您声称的std::map&lt;std::string, unsigned int&gt;。为了避免猜测迭代器的正确类型,只需使用auto,如auto it = myMap.find(key); 还要注意myMap.insert 不会替换已存在键的值。整个段落可以替换为++myMap["value"]; - 这对新密钥和现有密钥都是正确的。 @IgorTandetnik Arg,你打败了我。像一个小时。在发布我的答案之前,我应该已经加载了 cmets。您已经用 2 个简单的 cmets 总结了我的全部答案 :( 【参考方案1】:

你 wouldn't be getting this error 如果你的声明实际上是:

std::map<std::string, unsigned int> myMap

你会 get this exact error 但是如果你的定义是偶然的:

std::map<std::string, long> myMap

Herb Sutter 在他著名的Almost Always Auto 中假设了该准则:

请记住,首选 auto 变量的主要动机是正确性、性能、可维护性和稳健性,最后才是打字方便。

正如 Herb Sutter 所建议的那样,auto(和make_pair)不仅可以使您的代码正确,而且还可以使其更加健壮,也就是说,它将支持myMap,而与您声明的上述哪个声明无关使用:

const string key = "value"s;
const auto it = arg.find(key);

if(it == arg.end()) 
    arg.insert(make_pair(key, 1));
 else 
    int prev_value = it->second;
    prev_value++;
    arg.insert(make_pair(key, prev_value));

Live Example

编辑:

Igor Tandetinik has reminded me那个map::insert

将元素插入容器,如果容器尚未包含具有等效键的元素

这意味着您的整个 else-block 不执行任何操作,因为它仅在 map 确实包含具有等效键的元素时才会触发。大概您打算使用map::insert_or_assign 或类似的,在这种情况下,您的整个代码应该简单地替换为:

++myMap["value"s]

EDIT2:

请注意,上述方法之所以有效,是因为在 C++ 中,下标运算符的优先级高于前缀自增运算符。但是 myMap["value"s]++ 将不起作用,因为后缀增量的优先级高于下标运算符。有关运算符优先级的更多信息,请参阅C++ operator precedence chart。

在这种情况下,这种排序是一件好事,因为它迫使您做出更好的编码决策。具体来说,在 C++ 中,出于优化原因,最佳实践是使用 prefix 增量运算符而不是 postfix 增量运算符(尽管在大多数情况下,现代编译器会为您提供最好的实践仍然有效。)

【讨论】:

“将大大简化” 不仅简化,而且修复错误。在原始代码中,整个else 子句是一个精心设计的无操作,因此映射只包含1s。 @IgorTandetnik 大概这段代码会被迭代运行,所以 else 条件会产生影响...... 它不可能有影响——它没有副作用。 @IgorTandetnik 我对迭代的假设是key 会改变。 您认为key 会在arg.find(key)arg.insert(make_pair(key, prev_value)) 调用之间发生变化吗?因为否则,insert 会使用已知存在于映射中的键调用,在这种情况下,insert 是无操作的。

以上是关于在字符串的 std::map 中查找编译错误,长的主要内容,如果未能解决你的问题,请参考以下文章

GTEST 中 std::map 和 dense_hash_map 的编译器错误

使用 lambda 对 std::map 进行排序

将 std::map 转换为有序的 std::vector

优化查找和排序

CLion无法解析类型std :: unordered_map,即使它提示我包含标题和编译工作

在 std::map 中查找最接近或准确的键