使用 Fstream 序列化无序映射
Serialization of Unordered Map Using Fstream
我需要序列化无序地图。下面的方法使用 fstream
以二进制方式读写数据到 map 中。但是,在清除地图并将其重新加载后,它会打印 0
而不是 5
。这些函数在修改为与 vector
而不是 unordered_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];
}
容器序列化是一个小问题,因为unordered_map
它是作为哈希表实现的,它的实现有些复杂,你可以从这个picture.
中一窥究竟
在您的代码中,您希望 unordered_map
具有起始地址 (char*) p_map_ptr
和固定大小 sizeof(*p_map_ptr)
并且具有连续的内存布局,这是错误的。
起始地址(char*) p_map_ptr
是unordered_map
的地址,可能是一个bucket vector的地址,与元素地址无关,元素存放在链表中存储在存储桶中。
大小sizeof(*p_map_ptr)
只是unordered_map
的大小,不是所有元素的大小,如果我们把它改成p_map_ptr->sizes() * sizeof(decltype(p_map_ptr)::value_type)
它会得到所有元素的总大小,但是我们仍然不能使用这个大小来复制内存。由于std::unrodered_map
的内存布局是分散的
一个相当大的选择是使用 boost serialization:
#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
相关答案:要使用 进行序列化和反序列化,它比此处的二进制存档更具可读性但性能较低。
我需要序列化无序地图。下面的方法使用 fstream
以二进制方式读写数据到 map 中。但是,在清除地图并将其重新加载后,它会打印 0
而不是 5
。这些函数在修改为与 vector
而不是 unordered_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];
}
容器序列化是一个小问题,因为unordered_map
它是作为哈希表实现的,它的实现有些复杂,你可以从这个picture.
在您的代码中,您希望 unordered_map
具有起始地址 (char*) p_map_ptr
和固定大小 sizeof(*p_map_ptr)
并且具有连续的内存布局,这是错误的。
起始地址(char*) p_map_ptr
是unordered_map
的地址,可能是一个bucket vector的地址,与元素地址无关,元素存放在链表中存储在存储桶中。
大小sizeof(*p_map_ptr)
只是unordered_map
的大小,不是所有元素的大小,如果我们把它改成p_map_ptr->sizes() * sizeof(decltype(p_map_ptr)::value_type)
它会得到所有元素的总大小,但是我们仍然不能使用这个大小来复制内存。由于std::unrodered_map
的内存布局是分散的
一个相当大的选择是使用 boost serialization:
#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
相关答案:要使用