首页 > 解决方案 > 使用 Fstream 序列化无序映射

问题描述

我需要序列化一个无序的地图。下面的方法用于fstream以二进制模式读取和写入数据到映射中。但是,它会在清除地图并将其重新加载后打印0而不是打印。这些功能在修改为与 a而不是一起使用时可以正常工作。5vectorunordered_map

#include <iostream>
#include <unordered_map>
#include <fstream>

using namespace std;

void saveData(unordered_map<int, int>* p_map_ptr) {
    fstream file("data.bin", ios::out | ios::binary);

    file.seekp(0);
    file.write((char*) p_map_ptr, sizeof(*p_map_ptr));
    file.close();
}

void loadData(unordered_map<int, int>* p_map_ptr) {
    fstream file("data.bin", ios::in | ios::binary);

    file.seekg(0);
    file.read((char*) p_map_ptr, sizeof(*p_map_ptr));
    file.close();
}

int main() {
    unordered_map<int, int> map;

    map[0] = 5;
    saveData(&map);
    map.clear();
    loadData(&map);

    cout << map[0];
}

标签: c++fileserializationfile-ioio

解决方案


容器序列化是一个小问题,因为它是作为一个哈希表来实现的,它的实现有点复杂,从这张unordered_map你可以看出来。

在您的代码中,您应该unordered_map有一个起始地址(char*) p_map_ptr和一个固定的大小sizeof(*p_map_ptr)并且具有连续的内存布局,这是错误的。

开始地址(char*) p_map_ptrunordered_map的地址,它可能包含一个桶向量的地址,与元素的地址无关,元素存储在列表中,存储在桶中。

sizesizeof(*p_map_ptr)只是unordered_map的大小,不是所有元素的大小,如果我们改成它p_map_ptr->sizes() * sizeof(decltype(p_map_ptr)::value_type)会得到所有元素的总大小,但是我们仍然不能使用这个大小来复制内存。由于内存布局std::unrodered_map是分散的。

一个相当大的选择是使用boost 序列化

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/unordered_map.hpp>
#include <fstream>
#include <iostream>
#include <unordered_map>

using namespace std;

void saveData(const unordered_map<int, int>& map,
              const std::string& file = "data.bin") {
  std::ofstream filestream(file);
  boost::archive::binary_oarchive archive(filestream,
                                          boost::archive::no_codecvt);

  archive << map;
}

void loadData(unordered_map<int, int>* p_map_ptr,
              const std::string& file = "data.bin") {
  std::ifstream filestream(file);
  boost::archive::binary_iarchive archive(filestream,
                                          boost::archive::no_codecvt);

  archive >> *p_map_ptr;
}

int main() {
  unordered_map<int, int> map;

  map[0] = 5;
  map[1] = 6;
  saveData(map);
  map.clear();
  loadData(&map);

  cout << map[0];
}

要构建代码,我们需要添加一个链接标志,对于 Linux:-lboost_serialization

相关答案:要使用文本存档进行序列化和反序列化,它比此处的二进制存档更易于阅读,但性能较低。


推荐阅读