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

用智能指针指向vector中Station元素的C++带权有向图实现问题

问题解答

一、智能指针指向vector中Station元素的方式是否正确?

首先,当前你的实现存在两个关键问题:

  1. 智能指针类型冗余:std::shared_ptr<Station*>是指向Station*的智能指针,完全没必要多这一层指针嵌套。我们只需要直接用std::shared_ptr<Station>来管理Station对象的生命周期即可,额外的指针层级只会增加代码复杂度和出错概率。

  2. vector元素地址失效风险:std::vector在扩容时会重新分配内存,原有元素的地址会失效。如果直接把vector中元素的原始地址存入shared_ptr,后续vector扩容(比如添加新站点)时,这些指针会变成悬空指针,触发未定义行为。

修正方案:

  • 修改Road类的nextStation类型为std::shared_ptr<Station>
  • 将TransportationSystem中的stations容器改为std::vector<std::shared_ptr<Station>>,让所有Station对象都由智能指针管理,这样即使vector扩容,智能指针的指向也不会失效。

修改后的核心类成员:

// Road类中
std::shared_ptr<Station> nextStation;

// TransportationSystem类中
std::vector<std::shared_ptr<Station>> stations;

对应的节点查找逻辑也要调整为基于智能指针的匹配:

// 查找源节点的示例
auto sourceNodeIt = find_if(stations.begin(), stations.end(), 
    [&sourceNode](const std::shared_ptr<Station>& s) {
        return s->getStationName() == sourceNode;
    });

二、完善目标节点不存在时的处理逻辑

当目标节点不存在时,我们需要先创建对应的Station对象(用智能指针管理),将其添加到stations容器中,再让当前Road的nextStation指向它,最后把Road添加到源节点的道路列表中。如果源节点也不存在,也可以按相同逻辑创建源节点。

完整处理代码:

void TransportationSystem::loadAll() {
    for (const auto& fileName : inputFiles) {
        ifstream infile(fileName);
        string sourceNode;
        string targetNode;
        int distance;
        string transportationType = getTransportationTypeByFileName(fileName);
        string sourceStationType;
        string targetStationType;

        while (infile >> sourceNode >> targetNode >> distance) {
            Road r;
            if (defaultValues) {
                r.setDefaultValues(transportationType, sourceNode, targetNode, distance);
            } else {
                r.setNonDefaultValues(transportationType, sourceNode, targetNode, distance, getTransitionTimeByTransportationType(transportationType));
            }

            // 获取源和目标站点的类型
            sourceStationType = getStationTypeBySourceNode(sourceNode);
            targetStationType = getStationTypeBySourceNode(targetNode);

            // 查找源节点
            auto sourceNodeIt = find_if(stations.begin(), stations.end(), 
                [&sourceNode](const std::shared_ptr<Station>& s) {
                    return s->getStationName() == sourceNode;
                });

            // 查找目标节点
            auto targetNodeIt = find_if(stations.begin(), stations.end(), 
                [&targetNode](const std::shared_ptr<Station>& s) {
                    return s->getStationName() == targetNode;
                });

            std::shared_ptr<Station> sourceStation;
            // 处理源节点不存在的情况
            if (sourceNodeIt == stations.end()) {
                int sourceWaitingTime = getWaitingTimeByStationType(sourceStationType);
                sourceStation = std::make_shared<Station>(sourceNode, sourceStationType, sourceWaitingTime);
                stations.push_back(sourceStation);
            } else {
                sourceStation = *sourceNodeIt;
            }

            std::shared_ptr<Station> targetStation;
            // 处理目标节点不存在的情况
            if (targetNodeIt == stations.end()) {
                int targetWaitingTime = getWaitingTimeByStationType(targetStationType);
                targetStation = std::make_shared<Station>(targetNode, targetStationType, targetWaitingTime);
                stations.push_back(targetStation);
            } else {
                targetStation = *targetNodeIt;
            }

            // 绑定Road的目标站点并添加到源站点的道路列表
            r.nextStation = targetStation;
            sourceStation->addRoad(r);
        }
    }
}

额外注意事项:

  • 建议用find_if替代find来匹配节点,避免依赖Station::operator==的具体实现(如果原operator==不是仅按站点名称比较,会导致匹配错误)。
  • 如果业务需求中不允许自动创建不存在的站点,可以在节点不存在时抛出CouldNotOpenFileException或自定义异常,跳过当前道路的加载。

内容的提问来源于stack exchange,提问作者Amir Baum

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:18:09