如何使引用指向std::unordered_map其他节点并解决编译报错
问题背景
我有一个std::unordered_map<int, int>容器,用于存储给定数组中各元素的出现频次,需要找出频次最高的元素,打印其对应的键与频次计数。
初始实现代码如下:
#include <iostream> #include <unordered_map> #include <type_traits> int main() { std::unordered_map<int, int> mp { { 1, 2 }, { 2, 54 }, { 3, 32 }, { 4, 8 }, { 5, 56 }, { 6, 23 }, { 7, 9 }, { 8, 87 }, { 9, 69 }, }; auto maxP = std::ref(*mp.begin()); for (const auto& p : mp) { if (p.second > maxP.get().second) maxP = std::ref(std::add_lvalue_reference<std::pair<const int, int>&>(std::remove_const<const std::pair<const int, int>>(std::remove_reference<const std::pair<const int, int>&>(p)))); } std::cout << maxP.get().first << ", " << maxP.get().second << std::endl; }
编译上述代码时触发报错:
<Main.cpp>:21:191: error: no matching function for call to 'std::remove_reference<const std::pair<const int, int>&>::remove_reference(const std::pair<const int, int>&)' 21 | maxP = std::ref(std::add_lvalue_reference<std::pair<const int, int>&>(std::remove_const<const std::pair<const int, int>>(std::remove_reference<const std::pair<const int, int>&>(p)))); |
原实现思路是通过std::ref保存遍历过程中当前频次最高的节点引用,遍历到频次更高的节点时更新引用指向,但误用std::remove_reference、std::remove_const等类型萃取工具构造引用时触发了上述编译错误,需要正确的实现方案。
错误原因
std::remove_reference、std::remove_const、std::add_lvalue_reference都属于编译期类型萃取工具,仅用于对类型做编译期转换,不是可以传入实例对象调用的运行时函数。原代码中把这些类型模板当作可调用对象传入变量p,编译器找不到对应的函数签名,自然抛出匹配错误。
正确实现
不需要做任何多余的类型转换,遍历过程中拿到的p本身就是符合要求的const左值引用,可以直接传给std::ref,std::reference_wrapper的赋值运算符本身就支持重新绑定到新的引用对象。
修正后的代码如下:
#include <iostream> #include <unordered_map> #include <functional> // std::ref 依赖该头文件 int main() { std::unordered_map<int, int> mp { { 1, 2 }, { 2, 54 }, { 3, 32 }, { 4, 8 }, { 5, 56 }, { 6, 23 }, { 7, 9 }, { 8, 87 }, { 9, 69 }, }; // 边界情况处理:空map直接返回 if (mp.empty()) { return 0; } auto maxP = std::ref(*mp.begin()); for (const auto& p : mp) { if (p.second > maxP.get().second) { maxP = std::ref(p); } } std::cout << maxP.get().first << ", " << maxP.get().second << std::endl; }
运行上述代码会正确输出结果:8, 87
注意点:
- 使用
std::ref必须包含<functional>头文件,原代码遗漏该头文件在部分编译环境下也会触发错误 - 增加空map判断,避免对空容器解引用
begin()迭代器触发未定义行为
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

