我想在将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
}
}
怎么做?
答案 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
存储在map
,list
或其他任何内容中。然后,您可以便宜且轻松地复制它们,而无需复制基础数据。您仍然可以获得(或多或少)值语义,并且不需要手动管理对象生存期。