C++嵌套std::map查找实现及.at、[]运算符使用咨询
你的实现存在3个会直接导致编译失败的问题,无法正常工作
- 返回值类型不匹配:函数声明的返回值是
float(基础数值类型),但你在不存在分支返回字符串字面量"NaN",二者类型完全不兼容,编译器会直接报错。如果要返回浮点标准定义的非数值,需要用std::numeric_limits<float>::quiet_NaN(),使用前要包含<limits>头文件;如果你需要返回字符串形式的"NaN",必须把函数返回值改成std::string。 - 违反const语义:这个方法是const成员函数,意味着函数内部不能修改成员变量
registration_by_date_time,但你最后返回值时用了map的下标运算符[]——map的[]没有const版本,它的设计逻辑是如果查询的键不存在,就自动插入一个默认构造的对应值,本质是修改操作,所以const上下文里根本不能调用[]。 - 冗余拉低效率:你对外层键
date做了至少3次重复的O(logn)查找(第一次find、两次at、最后一次[]),完全没必要,一次查找拿到迭代器就能复用结果。
你问的几个API使用问题解答
.at()方法用对了吗?
这部分逻辑没大问题:你先用find确认了date在外层map里存在,此时调用.at(date)肯定能拿到对应的内层map引用,不会触发.at()找不到键时抛std::out_of_range异常的逻辑。而且.at()是有const重载的,const上下文里调用是合法的,唯一的问题是重复调用做了多余查找。
能不能用下标运算符[]?
- 在当前const修饰的成员函数里绝对不能用,原因前面说过,
[]会潜在修改map,编译器直接拦截。 - 就算你把函数的const限定去掉,也不推荐用:只要判断逻辑有一点疏漏,
[]就会往map里插入你不需要的空内层map,平白污染原始数据。
能不能用second成员实现?
不仅可以,这还是最高效的写法。map::find()返回的迭代器指向的是std::pair<const 键类型, 值类型>结构,first存键,second存对应的值,拿到迭代器之后直接访问second不需要再做键查找,比反复调用at、[]少了多次对数时间复杂度的查询,性能最好。
修正后的可运行实现
先引入必要的头文件:
#include <map> #include <string> #include <limits>
符合你原有函数签名(返回float类型NaN)的实现:
float get_registration(const std::string & date, const std::string & time) const{ // 外层日期只查一次 auto date_it = registration_by_date_time.find(date); if (date_it == registration_by_date_time.cend()) { return std::numeric_limits<float>::quiet_NaN(); } // 直接拿迭代器指向的内层map的const引用,不用重复查外层 const auto& time_map = date_it->second; auto time_it = time_map.find(time); if (time_it == time_map.cend()) { return std::numeric_limits<float>::quiet_NaN(); } // 取内层迭代器的值返回 return time_it->second; }
如果你确实需要返回字符串形式的"NaN",把函数返回值改成std::string,不存在的分支直接返回"NaN",存在的分支用std::to_string(time_it->second)把浮点值转成字符串返回即可。
内容的提问来源于stack exchange,提问作者Fabio
相关产品推荐
相关产品推荐

