包含另一个地图的对象的 C++ 地图插入问题

C++ map insert problem with objects containing another map

我有包含其他地图的无序地图容器。

using name = std::string;
using stop_o = std::pair<name, std::unordered_map<key,/**/ std::pair<name, std::unordered_map<key, std::pair<name, std::map<packed_time, std::pair<packed_time, std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>>>>>>>;
using platform_o = std::pair<name, std::unordered_map<key,/**/ std::pair<name, std::map<packed_time, std::pair<packed_time, std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>>>>>;
using platform_route_o = std::pair<name, std::map<packed_time,/**/ std::pair<packed_time, std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>>>;
using route_departure_o = std::pair<packed_time,/**/ std::pair < int, std::map<int, std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>>;
using trip_o = std::pair < int, std::map<int,/**/ std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>>>;
using trip_departure_o = std::pair<int, std::pair<packed_time, std::pair<name, timetable*>>>;

trip_o只是一对int和trip_departure_o。 然后我正在使用容器:

using stop_container = std::unordered_map<key, stop_o>;
using platform_container = std::unordered_map<key, platform_o>;
using platform_route_container = std::unordered_map<key, platform_route_o>;
using route_departure_container = std::map<packed_time, route_departure_o>;
using trip_container = std::unordered_map < int, trip_o>;
using trip_departure_container = std::map<int, trip_departure_o>;

// main object - put something inside
class timetable {
    public:
    stop_container timetable_stops;
    trip_container timetable_trips;
};

我的代码是:

void read_timetable(timetable& tt, std::istream& ifs)
{
    std::string line, token;
    ifs.ignore(1000, '\n');
    while (std::getline(ifs, line, '\n'))
    {
        std::vector<std::string> v;
        std::stringstream entry(line);
        while (std::getline(entry, token, '\t'))
        {
            v.push_back(token);
        }
        std::vector<int> time;
        std::stringstream t(v[5]);
        while (std::getline(t, token, ':'))
        {
            time.push_back(stoi(token));
        }
        packed_time pt = pack_time(time[0], time[1]);

        if (tt.timetable_stops.find(v[4]) == tt.timetable_stops.end())
        {
            trip_departure_o td;
            td.first = stoi(v[2]);
            td.second.first = pt;
            td.second.second.first = v[4];
            td.second.second.second = &tt;

            trip_o tr;
            tr.first = stoi(v[1]);
            tr.second.insert({ stoi(v[1]), td });
            std::cout << tr.second.at(stoi(v[1])).first << std::endl;

            route_departure_o rd;
            rd.first = pt;
            rd.second = tr;
            std::cout << rd.second.first << std::endl;

            platform_route_o pr;
            pr.first = v[0];
            pr.second.insert({ pt, rd });
            std::cout << pr.second.at(pt).first << std::endl;

            platform_o p;
            p.first = v[3];
            p.second.insert({ v[3], pr });

            stop_o s;
            s.first = v[4];
            s.second.insert({ v[4], p });
            std::cout << s.second.at(v[4]).first << std::endl;

            tt.timetable_stops.insert({ v[4], s });

            std::cout << tt.timetable_stops.at(v[4]).second.at(v[3]).first;
            }
        }
... .. .

我每次都将输入的行拆分为 6 个标记。然后我将最后一个标记(时间)转换为小时和分钟并将其打包为一个整数。 现在问题来了。我成功创建了 trip_departure td,测试输出我知道里面有所有变量。然后我初始化 trip_o tr。第一个变量在那里,但是当我想得到第二个实际上是前一个对象 td 时,我得到一个错误:

jr.exe 中 0x00007FFCBF09D759 的未处理异常:Microsoft C++ 异常:std::invalid_argument 在内存位置 0x0000007FF891D410。

这一行抛出异常:

std::cout << tt.timetable_stops.at(v[4]).second.at(v[3]).first;

它似乎没有插入到地图中。但是为什么?

问题出在第二个 atv[3]

第一个 at returns 对添加到时间表的 s 副本的引用停止。该副本在 v[4] 处有一个元素,而不是 v[3]。所以你要么想要

tt.timetable_stops.at(v[4]).second.at(v[4])

tt.timetable_stops.at(v[4]).second.at(v[4]).second.at(v[3])
//                 ^ returns copy of s
//                                  ^ returns copy of { v[4], p } originally stored in s
// returns copy of p stored in ...                 ^

如果您使用具有适当命名成员的适当结构而不是大量复杂的类型别名,这将更容易查看和诊断。