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) );
}

また、シリアル化するのと同じオブジェクトを逆シリアル化する必要があるため、唯一のクリーンな方法は、シリアル化を処理するマルチマップを含むオブジェクトをアーカイブに与えることです。そのオブジェクトは、マップを所有するクラスまたはダミーのいずれかです。ただし、これには既存の逆シリアル化コードにいくつかの変更を加える必要があります。

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

ダミーのコンストラクターは、接続の生成に必要なオブジェクトへのポインター(保存時)またはマルチマップへのポインター(ロード時)のいずれかを取得します。ダミーのメソッドは、メソッドがマルチマップを埋めるだけsave()で、接続オブジェクトをその場で生成、保存、および削除できます。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 に答える