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

从std::map迭代访问其second成员内的std::deque元素时出现指针地址重复及访问异常问题

从std::map迭代访问其second成员内的std::deque元素时出现指针地址重复及访问异常问题

兄弟,你这个问题的核心是局部对象生命周期结束后产生的悬空指针,再加上容器返回值的小坑,咱们一步步拆解清楚:

问题1:局部变量Ruta ruta导致的悬空指针

你在addNuevaRuta函数里创建了一个局部的Ruta ruta对象,然后通过linkAeroRuta把这个局部对象的指针存到了Aerolinea的aeroroutes deque里。但局部变量的生命周期只限于函数内部——当addNuevaRuta执行完毕,这个ruta就会被销毁,对应的内存地址就变成了无效的「悬空指针」。

而且因为栈内存的复用特性,每次调用addNuevaRuta时,这个局部变量在栈上的位置大概率是重复的,所以你会看到所有输出的指针地址完全一样。这时候你再通过这些指针访问对象成员,属于未定义行为,自然会得到错误的输出。

问题2:getRutas()返回容器副本而非引用

你的Aerolinea::getRutas()方法返回的是std::deque<Ruta*>的副本,不是引用。这意味着你在迭代it_airlines.second.getRutas()的时候,其实是在操作一个临时生成的deque副本——虽然这不是你当前问题的核心,但会带来不必要的性能开销,甚至可能引发其他隐藏问题。


修复方案

1. 解决悬空指针问题:确保Ruta对象的生命周期有效

你需要让aeroroutes里存储的指针指向一个生命周期足够长的对象,这里有两种靠谱的思路:

思路A:复用你已有的routes容器

你已经在VuelaFlight里有一个routes容器,用来存储Ruta对象。那我们可以直接在这个容器里构造对象,然后把容器内对象的地址存入aeroroutes:

void VuelaFlight :: addNuevaRuta(const std::string &icao,
const std::string &idAeroOrig,
const std::string &idAerDest){

// 直接在routes容器末尾构造新的Ruta对象,获取它的引用
this->routes.emplace_back();
Ruta& ruta = this->routes.back();

auto airline_it = this->airlines.lower_bound(icao);
if(airline_it == this->airlines.end()){
    throw std::out_of_range("VuelaFlight :: addNuevaRuta -> No existe aerolinea con esa identificacion");
}
ruta.setCompany(&airline_it->second);

Aeropuerto airport;
airport.setIata(idAeroOrig);
auto it_airport = std::lower_bound(this->airports.begin(), this->airports.end(),airport);
ruta.setOrigin(it_airport.base());

airport.setIata(idAerDest);
it_airport = std::lower_bound(this->airports.begin(), this->airports.end(),airport);
ruta.setDestination(it_airport.base());

// 现在存的是routes容器内对象的地址,生命周期和容器一致
airline_it->second.linkAeroRuta(ruta);
}

思路B:使用智能指针管理动态分配的对象

如果你不想依赖routes容器,也可以用std::shared_ptr或std::unique_ptr来管理Ruta对象的内存,避免手动释放:

// 修改Aerolinea的aeroroutes为智能指针容器
std::deque<std::shared_ptr<Ruta>> aeroroutes;

// 修改linkAeroRuta方法
void Aerolinea::linkAeroRuta(std::shared_ptr<Ruta> ruta) {
    this->aeroroutes.push_back(ruta);
}

// 修改addNuevaRuta
void VuelaFlight :: addNuevaRuta(const std::string &icao,
const std::string &idAeroOrig,
const std::string &idAerDest){

auto ruta = std::make_shared<Ruta>();

auto airline_it = this->airlines.lower_bound(icao);
if(airline_it == this->airlines.end()){
    throw std::out_of_range("VuelaFlight :: addNuevaRuta -> No existe aerolinea con esa identificacion");
}
ruta->setCompany(&airline_it->second);

// ... 其他逻辑不变 ...

airline_it->second.linkAeroRuta(ruta);
this->routes.push_back(*ruta); // 如果还需要存副本的话
}

2. 修改getRutas()返回引用

把getRutas改成返回容器的引用,避免不必要的拷贝:

// 非const版本,允许修改容器
std::deque<Ruta*>& Aerolinea :: getRutas(){
    return this->aeroroutes;
}

// const版本,用于只读场景
const std::deque<Ruta*>& Aerolinea :: getRutas() const {
    return this->aeroroutes;
}

补充说明

为什么你在linkAeroRuta里访问是正常的?因为那时候局部变量ruta还在函数的生命周期内,指针是有效的;但函数执行完毕后,这个对象就被销毁了,之后再访问这些指针就属于未定义行为,结果自然是错误的。

备注:内容来源于stack exchange,提问作者Juan Montes Trujillo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 07:13:09