You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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异常,你的代码里有两个触发异常的风险点:

  1. 调用flights.at(from)时,如果from对应的城市没有航班记录(甚至from本身未被添加到cities中),会直接抛异常;
  2. 调用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;
}

额外优化建议

  1. 在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);
}
  1. 若你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:22:42