4

私はC++ブーストが初めてなので、この質問は基本的なものかもしれません:ポインターで相互に参照する2つのクラスをシリアル化する方法. 例えば:

class A;
class B;

class A {
  public:
  ...
  private:
    double a;
    vector <B*> b;
}

class B {
  public:
  ...
  private:
    int b;
    list <A*> a;
}

クラス A にはポインタ B* を含むプライベート ベクトルがあり、クラス B には A* を含むプライベート リストがあります。

特に Deserialization では問題が発生します (ポインター!)。誰にもアイデアはありますか?

4

2 に答える 2

3

オブジェクト追跡のおかげで、Boost.Serialization はポインターの循環参照を適切に処理します。ポインターを使用してオブジェクトをシリアル化する場合、既定でオブジェクト トラッキングが使用されます。std::vector(include )のシリアライザーも付属していboost/serialization/vector.hppます。

Boost.Serialzation は、シリアル化するオブジェクトのアドレスを追跡します。既にシリアル化されているアドレスに遭遇した場合、再度シリアル化するのではなく、オブジェクトへの「参照」を保存します。

デシリアライズするとき、これらの参照を見つけたときに適切なアドレスに解決します (これは、アドレスを割り当てることができるように、それらがポインターでなければならないことを意味します)。

唯一の制限は、参照されるオブジェクトが (ヒープ上で) 動的に割り当てられる必要があることです。別のオブジェクトから参照されていない限り、スタック上のオブジェクトをシリアル化できます。

A a;
B b;
a.vec.push_back( &b ); // WRONG! deserialization will crash
// if a does not reference to b, it will work
archive << a << b;

その理由は次のとおりです。bは、a を(そのベクトルで)シリアル化するときにポインターとして最初に検出されます。b自体をシリアル化すると、 bへの参照のみが格納されます。

A a;
B b;
archive >> a >> b; // crashes when deserializing b!

a を逆シリアル化すると、bがベクターに割り当てられます。そして、スタック上に既に存在するbを復元したいとします。スタック上の変数に新しいアドレスを割り当てることができないため、クラッシュします!

正しい:

A* a = new A();
B* b = new B();
a.vec.push_back(b); // OK! this works fine

bを逆シリアル化する場合、boost は単に a のベクトル内の b のアドレスをそれ割り当てます

Boost.Serialzation にはboost::shared_ptr(include boost/serialization/shared_ptr.hpp) のシリアライザーも付属しており、代わりに使用することでタスクがさらに簡単になる可能性があるためstd::vector< boost::shared_ptr<A> >、メモリの解放を心配する必要はありません。

基本をカバーすると、クラスのシリアル化を次のように簡単に実装できます。

// add this to your classes you want to serialize
private:
    friend boost::serialization::access;
    template<class Archive>
    void serialize(Archive& ar, unsigned version) {
        //TODO: serialize other member variables
        ar & BOOST_SERIALIZATION_NVP(vec); // vec is a std::vector
    }

shared_ptrs のベクトルを使用することを選択した場合、変更は必要ありません (ヘッダーを含めるだけです)。

于 2012-12-27T23:53:20.517 に答える
0

基本的な考え方は、シリアル化によって無限ループが発生するため、yclic 参照を避けることです。

このチュートリアルによると、A と B のインスタンスの相互の非循環参照に問題はないはずです。

于 2012-12-27T23:09:07.813 に答える