C++ std::out_of_range异常修复:unordered_map的.at()问题排查
问题描述
运行代码时抛出以下错误:
terminate called after throwing an instance of 'std::out_of_range'
what(): _Map_base::at
我是C++新手,明确这个错误来自getDestinations()函数里的.at()调用,但不知道怎么修复。
相关代码
graph.h
#include <string> #include <vector> #include <unordered_map> using namespace std; // 创建城市结构体,包含名称和是否为国际城市的属性 struct City { string name; // 城市名称 bool isInternational; // 是否为国际城市 }; // 图类定义及函数声明 class Graph { public: // 添加城市、添加航班、判断可达性的函数声明 void addCity(const string& name, bool isInternational); void addFlight(const string& from, const string& to); bool canReach(const string& from, const string& to); // 获取城市列表和目的地列表的函数声明 vector<City> getCities() const; vector<City> getDestinations(const string& from) const; private: // 存储城市和航班邻接表的哈希表 unordered_map<string, City> cities; unordered_map<string, vector<string>> flights; };
getDestinations函数实现
// 获取指定城市的所有目的地城市 vector<City> Graph::getDestinations(const string& from) const { vector<City> result; for (const auto& destination : flights.at(from)) { result.push_back(cities.at(destination)); } return result; }
我试过用contains()或find()来访问from和destination,但没成功。
错误原因与修复方案
错误原因
std::unordered_map的.at()方法在键不存在时会直接抛出std::out_of_range异常,你的代码里有两个触发异常的风险点:
- 调用
flights.at(from)时,如果from对应的城市没有航班记录(甚至from本身未被添加到cities中),会直接抛异常; - 调用
cities.at(destination)时,如果某个目的地城市未被注册到cities哈希表,也会抛异常。
修复方案
用find()替代.at()即可解决问题,find()在键不存在时会返回end()迭代器,不会直接抛出异常。以下是修复后的getDestinations函数:
vector<City> Graph::getDestinations(const string& from) const { vector<City> result; // 先查找出发城市对应的航班列表 auto flightsIter = flights.find(from); if (flightsIter == flights.end()) { // 无航班记录,直接返回空列表 return result; } // 遍历所有目的地 for (const auto& destName : flightsIter->second) { auto cityIter = cities.find(destName); if (cityIter != cities.end()) { // 仅当目的地城市存在时,才加入结果列表 result.push_back(cityIter->second); } // 可选:如果目的地不存在,打印警告信息 // else { // cerr << "警告:目的地城市 " << destName << " 未注册" << endl; // } } return result; }
额外优化建议
- 在
addFlight中提前校验城市合法性,避免无效航班被添加:
void Graph::addFlight(const string& from, const string& to) { if (cities.find(from) == cities.end() || cities.find(to) == cities.end()) { cerr << "错误:出发地或目的地城市未注册" << endl; return; } flights[from].push_back(to); }
- 若你的C版本是C20及以上,也可以用
contains()简化判断逻辑(contains()会直接返回键是否存在的布尔值):
vector<City> Graph::getDestinations(const string& from) const { vector<City> result; if (!flights.contains(from)) { return result; } // 已经确认键存在,此时用.at()不会抛异常 for (const auto& destName : flights.at(from)) { if (cities.contains(destName)) { result.push_back(cities.at(destName)); } } return result; }
内容的提问来源于stack exchange,提问作者tobawoniyi
相关产品推荐
相关产品推荐

