1

std::multimap<Participant*, Connection*>以前我的程序在完全填充后用于序列化整个程序。这对于保存和恢复都很简单arc & _connections

但这需要每个连接对象都留在内存中。但我不需要这些对象来进行序列化以外的任何事情。因此,为了最大限度地减少内存消耗,它决定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;

我不确定应该怎么做。只是猜测。

4

1 回答 1

0

我知道您要做什么,但我不推荐它,因为它很容易损坏。例如,如果您将存档更改为 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) );
}

您还必须反序列化您正在序列化的同一对象,因此唯一干净的方法是为存档提供一个包含处理序列化的 multimap 的对象。该对象可以是拥有地图的类或虚拟对象。但是,这将需要对现有的反序列化代码进行一些更改:

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

dummy 的构造函数将采用指向生成连接所需的对象的指针(保存时)或指向多映射的指针(加载时)。然后,假人的save()方法可以即时生成、存储和删除 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()
// }

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

于 2012-11-18T15:57:44.517 回答