std :: map to std :: list导致SIGSEGV

时间:2018-06-05 11:14:35

标签: c++ stdmap sigsegv stdlist

我想在将std :: map转换为std :: list时保存RAM。因此,我必须删除其间的每个元素。但是我得到了一个SIGSEGV。

template <class U>
auto ConvertFlatSegmentsMapToList(std::map<std::string /* relative_path */, U>& differences_map, std::list<U>& differences_list) -> void {
    for (auto& i:differences_map) {
        differences_list.push_back(i.second);
        // differences_map.erase(i.first);//TODO: SIGSEGV
    }
}

怎么做?

3 个答案:

答案 0 :(得分:3)

如果您想节省内存,请不要使用std::map,也不要std::list - 使用std::vector;或者更好 - 不要使用单独的字符串,应用重复数据删除等。

话虽如此,并回答你的问题:将地图invalidates iterators中的元素删除到地图中 - 并且ranged-for循环实际上是基于迭代器。所以 - 你不能在你的循环中删除。循环后使用differences_map.clear()。您还应该注意,单个元素删除的时间比清除整个地图要贵得多。

如果您的记忆受到限制,以至于您无法同时使用完整地图和完整列表,那么您只是使用了错误的数据结构 - 因为,就像我说的那样,这两者都是很浪费但是,如果你坚持,你可以反复将*differences_map.begin()插入到列表中,然后将其从地图中删除(并且每次在迭代器失效后再次获得.begin())。

答案 1 :(得分:1)

正如yussuf评论的那样,您可以在https://stackoverflow.com/a/8234813/1142788找到解决方案。我已经根据我的例子进行了调整。 (需要c ++ 11支持)

template <class U>
auto ConvertFlatSegmentsMapToList(std::map<std::string /* relative_path */, U>& differences_map, std::list<U>& differences_list) -> void {
    std::clog << "differences_map: " << differences_map.size() << std::endl;    // e.g. 6
    std::clog << "differences_list: " << differences_list.size() << std::endl;  // e.g. 0

    for (auto i = differences_map.cbegin(); i != differences_map.cend(); i = differences_map.erase(i)) {
        differences_list.push_back(i->second);
    }

    std::clog << "differences_map: " << differences_map.size() << std::endl;    // e.g. 0
    std::clog << "differences_list: " << differences_list.size() << std::endl;  // e.g. 6
}

答案 2 :(得分:0)

您可以考虑将std::shared_ptr存储在maplist或其他任何内容中。然后,您可以便宜且轻松地复制它们,而无需复制基础数据。您仍然可以获得(或多或少)值语义,并且不需要手动管理对象生存期。