手动提升序列化多映射

boost serialization multimap manually

本文关键字:映射 序列化 升序      更新时间:2023-10-16

以前,我的程序用于在整个std::multimap<Participant*, Connection*>完全填充后对其进行序列化。这对于保存和恢复来说都是简单的CCD_ 2。

但这需要每个连接对象都留在内存中。但除了序列化之外,我不需要这些对象。因此,为了最大限度地减少内存消耗,它决定在创建std::make_pair(connection->participant(), connection)后立即对其进行序列化。并在序列化完成后删除。

在填充开始之前,多映射的预期大小是已知的。

我想要的是手动序列化这些对,这样我就不需要更改反序列化代码,只需arc & _connections;

boost/serialization/collections_save_imp.hpp我看到

boost::serialization::save_construct_data_adl(
ar, 
&(*it), 
boost::serialization::version<BOOST_DEDUCED_TYPENAME Container::value_type>::value
);
ar << boost::serialization::make_nvp("item", *it++);

那么我应该使用类似的东西吗

typedef std::pair<Participant*, Connection*> PairT;
ar <<  BOOST_SERIALIZATION_NVP(expected_size);
if(3 < ar.get_library_version()){// I don't really understand this magic number here
const unsigned int item_version = boost::serialization::version<PairT>::value;
ar << BOOST_SERIALIZATION_NVP(item_version);
}
PairT pair = std::make_pair(connection->participant(), connection);
boost::serialization::save_construct_data_adl(
ar, 
pair, 
boost::serialization::version<PairT>::value
);
ar << boost::serialization::make_nvp("item", pair);
delete connection;

我不知道该怎么做。只是猜测。

我知道你想做什么,但我不建议你这样做,因为它很容易坏。例如,如果您将归档更改为xml,它将不起作用。如果您升级到更新的版本的boost,它可能也会崩溃,并且可能很难调试。原因是存档本身可能会在start_save()(例如类id)中添加一些额外的数据,然后执行实际的序列化并以对end_save()的调用结束。由于这些方法受保护,不能使用它们以可移植/稳定的方式"伪造"序列化。

您可以重写(专门化)多映射序列化,但这只会让您访问空容器,则必须使用一些技巧(如全局变量)来访问连接要序列化的对象:

template<class Archive>
inline void save(Archive& ar, const MultimapT& map, const unsigned version) {
Connection* p = new Connection( global_data->get(i) );
}

您还必须对正在序列化的同一对象进行反序列化,因此唯一干净的方法是为存档提供一个包含处理序列化的多映射的对象。该对象可以是拥有映射的类,也可以是伪对象。然而,这将需要对现有的反序列化代码进行一些更改:

ar << boost::serialization::make_nvp("map",Dummy(&_source));
// and
ar >> boost::serialization::make_nvp("map",Dummy(&_connections));

伪对象的构造函数将获取一个指向生成连接所需对象的指针(保存时)或指向多映射的指针(加载时)。假人的CCD_ 8方法然后可以生成,动态存储和删除Connection对象,而load()方法只是填充多映射。

当你在飞行中生成物体时,你必须禁用物体跟踪:

BOOST_CLASS_TRACKING(Connection, boost::serialization::track_never)
BOOST_CLASS_TRACKING(Participant, boost::serialization::track_never)

否则,存档检测到相同的内存地址被重复序列化,并将创建对第一个对象的引用,而不是实际存储数据。

以下是一个成员函数示例,用于演示包含多映射(伪类或父类)的对象的序列化:

// class Foo {
template<typename Archive>
inline void save( Archive& ar, const unsigned version ) const {
size_t count = expected_count();
ar << BOOST_SERIALIZATION_NVP(count);
for( size_t i=0; i<count; ++i ) {
Connection* connection = make_connection(i);
PairT pair(connection->participant(), connection);
ar << boost::serialization::make_nvp("item", pair);
delete connection;
}
}
template<typename Archive>
inline void load( Archive& ar, const unsigned version ) {
size_t count=0;
ar >> BOOST_SERIALIZATION_NVP(count);
while( count-- ) {
PairT pair;
ar >> boost::serialization::make_nvp("item", pair);
_connections->insert(pair);
}
}
friend boost::serialization::access;
BOOST_SERIALIZATION_SPLIT_MEMBER() // split serialize() into save() and load()
// }

参考文献:侵入式/非侵入式序列化、拆分保存和加载、对象跟踪