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

LEMON框架中类内ArcMap成员初始化与赋值问题求助

解决LEMON库中ListDigraph与ArcMap作为类成员的初始化问题

问题根源

  1. LEMON的ArcMap无默认构造函数,必须在构造时绑定到对应的Digraph对象
  2. 类定义中无法直接用同属类的ListDigraph成员初始化ArcMap,因为此时类对象未完成构造,成员未初始化
  3. ArcMap的赋值运算符为私有,无法先声明再绑定图对象

解决方案一:使用智能指针延迟初始化ArcMap

这种方式允许你在g完全构造后,再创建并绑定ArcMap:

  1. 修改类成员声明与compute_graph函数:
class GraphSolver {
public:
    void compute_graph() {
        // 初始化ArcMap,绑定到已构造的g
        length = std::make_unique<ListDigraph::ArcMap<int>>(g);

        for (auto const &t: seq_trips) {
            auto tid = t[0].trip_id;
            for (int i = 0; i < t.size() - 1; ++i) {
                auto from_sid = t[i].stop_id;
                auto to_sid = t[i + 1].stop_id;

                auto from_time = t[i].arrival_time;
                auto to_time = t[i + 1].arrival_time;
                auto delta = to_time - from_time;

                ListDigraph::Node from_node;
                ListDigraph::Node to_node;
                if (stop2node.find(from_sid) != stop2node.end())
                    from_node = stop2node.at(from_sid);
                else {
                    from_node = g.addNode();
                    stop2node[from_sid] = from_node;
                }
                if (stop2node.find(to_sid) != stop2node.end())
                    to_node = stop2node.at(to_sid);
                else {
                    to_node = g.addNode();
                    stop2node[to_sid] = to_node;
                }

                ListDigraph::Arc old_arc = findArc(g, from_node, to_node);

                if(old_arc == INVALID) {
                    ListDigraph::Arc new_arc = g.addArc(from_node, to_node);
                    (*length)[new_arc] = delta;
                }
                else {
                    if((*length)[old_arc] < delta)
                        (*length)[old_arc] = delta;
                }
            }
        }
    }

    // 其他成员声明
    SeqTrips seq_trips;
    MapStop2Idx stop2idx;
    VecStops stops;
    VecTrips trips;
    VecRoutes routes;
    ListDigraph g;
    unordered_map<size_t, ListDigraph::Node> stop2node;
    // 将ArcMap改为智能指针
    std::unique_ptr<ListDigraph::ArcMap<int>> length;
};

解决方案二:构造函数初始化列表(推荐)

通过构造函数初始化列表,利用成员声明顺序确保g先于ArcMap初始化:

  1. 调整成员声明顺序(必须g在前,length在后),并添加构造函数:
class GraphSolver {
public:
    // 构造函数初始化列表,用已初始化的g创建length和node2stop
    GraphSolver() : length(g), node2stop(g) {}

    void compute_graph() {
        for (auto const &t: seq_trips) {
            auto tid = t[0].trip_id;
            for (int i = 0; i < t.size() - 1; ++i) {
                auto from_sid = t[i].stop_id;
                auto to_sid = t[i + 1].stop_id;

                auto from_time = t[i].arrival_time;
                auto to_time = t[i + 1].arrival_time;
                auto delta = to_time - from_time;

                ListDigraph::Node from_node;
                ListDigraph::Node to_node;
                if (stop2node.find(from_sid) != stop2node.end())
                    from_node = stop2node.at(from_sid);
                else {
                    from_node = g.addNode();
                    stop2node[from_sid] = from_node;
                    node2stop[from_node] = from_sid;
                }
                if (stop2node.find(to_sid) != stop2node.end())
                    to_node = stop2node.at(to_sid);
                else {
                    to_node = g.addNode();
                    stop2node[to_sid] = to_node;
                    node2stop[to_node] = to_sid;
                }

                ListDigraph::Arc old_arc = findArc(g, from_node, to_node);

                if(old_arc == INVALID) {
                    ListDigraph::Arc new_arc = g.addArc(from_node, to_node);
                    length[new_arc] = delta;
                }
                else {
                    if(length[old_arc] < delta)
                        length[old_arc] = delta;
                }
            }
        }
    }

    // 成员声明顺序:先g,再依赖g的成员
    ListDigraph g;
    unordered_map<size_t, ListDigraph::Node> stop2node;
    ListDigraph::ArcMap<int> length;
    ListDigraph::NodeMap<int> node2stop; // 改为类成员,避免每次调用函数重新创建

    // 其他成员
    SeqTrips seq_trips;
    MapStop2Idx stop2idx;
    VecStops stops;
    VecTrips trips;
    VecRoutes routes;
};

关键注意点:C++类成员的初始化顺序严格按照类中声明的顺序,而非构造函数初始化列表的顺序。因此必须将g放在length和node2stop之前声明,否则会在未构造的g上创建ArcMap,导致未定义行为。


额外提示

原代码中node2stop是compute_graph内的局部变量,每次调用函数都会重新初始化。如果需要保留节点与站点的映射关系,建议将其改为类成员,如同方案二中的修改。

内容的提问来源于stack exchange,提问作者Claudio Tomasi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 15:35:37