代码之家  ›  专栏  ›  技术社区  ›  B. A. Sylla

STD::到STD::列表导致SIGSEV

  •  2
  • B. A. Sylla  · 技术社区  · 6 年前

    我想在STD::映射到STD::列表时保存RAM。因此,我必须删除中间的每个元素。但我得到了一个信号。

    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 回复  |  直到 6 年前
        1
  •  3
  •   einpoklum    6 年前

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

    这么说,并回答你的问题:从地图上删除一个元素 invalidates iterators 而ranged for循环实际上是基于迭代器的。所以-在循环期间不能删除。使用 differences_map.clear() 循环之后。您还应该注意,与清除整个映射相比,单个元素删除的时间开销要大得多。

    如果你的内存非常有限,以至于你不能同时拥有完整的映射和完整的列表,那么你只是使用了错误的数据结构——正如我所说,这两种结构都是非常浪费的。不过,如果你坚持,你可以反复插入 *differences_map.begin() 在列表中,然后从地图中删除它(每次获取 .begin() 同样,在迭代器失效之后)。

        2
  •  1
  •   B. A. Sylla    6 年前

    正如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
    }
    
        3
  •  0
  •   catnip    6 年前

    你可以考虑储存 std::shared_ptr 你的S map , list 或者别的什么。然后,您就可以轻松、廉价地复制它们,而无需复制底层数据。您仍然获得(或多或少)值语义,不需要手动管理对象生命周期。