如何序列化将指针保留在C++中的指针的对象

How to serialize an object that keeps pointers to other objects in C++?

本文关键字:指针 C++ 对象 保留 序列化      更新时间:2023-10-16

我正在寻找一种在C++中序列化大型复杂对象的方法。我一直在考虑使用提升序列化 api,但我不确定是否可以序列化以这种方式实现的对象。

在我的程序中,我有以下对象:

typedef map<float, float> SignalData;
typedef pair<float,float> TimeValuePair;
class SignalDatabaseNG : public SignalDatabase
{
   (...)
   private:
      vector<SingleSignal *> all_signals;
   (...)
};
class SingleSignalAsStdMap: public SingleSignal{
   private:
       SignalData * signalData;
   (...)
};
class IntegrationComparator : public Comparator {
   private:
      map<SignalData *, float> * preComputedIntegrals;
   (...)
   public:
       IntegrationComparator();
       float compare(SignalData *a, SignalData *b);
       void preComputeIntegralsForAll(SignalDatabase * database);
   (...)
 };

SignalDatabase 是一个类,其最重要的作用是保存程序所需的所有数据。信号表示为两个浮点数(时间和值)的映射,并且所有信号都保存在此类映射的向量中。

它通过以下方式填充数据:

SignalDatabaseNG * signalDatabase = TestConfiguration::getSignalDatabase();
IntegrationComparator * integrationComparator = new IntegrationComparator();
integrationComparator->preComputeIntegralsForAll(signalDatabase);

TestConfiguration::getSignalDatabase() 返回一个数据库对象,其中包含计算积分所需的数据(在程序运行时开始时从文本文件中读取)。然后,创建integrationComparator对象并调用preComputeIntegralsForAll(SignalDatabase * db),以执行计算。最后,integrationComparator内部的map<SignalData *, float> * preComputedIntegrals充满了数据。

这种积分计算需要大量时间(10 个信号大约需要 60 秒,我需要为 ~220000 个信号计算它)。

我希望能够运行它一次,然后序列化它,然后在每次程序运行时重用它(数据不经常更改,因此可以节省大量时间)。

问题在于映射将指向信号对象的指针映射到整数值。但是,在下一次运行中,数据库将从头开始创建,指针内的所有地址都将更改。可以序列化信号数据库和预计算的积分数据库,但也不能保证在反序列化后数据库中的信号会位于内存中的相同位置,因此积分比较器中的指针也是完全错误的。

有没有人知道如何完成这种序列化(最好,不必重写类的整个结构)?

boost 序列化可以处理指向对象的指针,即使它们是多态的。库将序列化指向的对象(并注册其类型),当从存档读取时,将创建对象的新实例,反序列化并填充指针。

这个问题的答案详细介绍了在反序列化时需要执行哪些操作来帮助库识别派生类。

这也适用于shared_ptrs和其他智能指针(提示,提示)。

此外,boost 序列化还可以为您跟踪对象,以便在序列化指向同一对象的两个指针时,该对象仅序列化一次。

设计中有趣的部分是使用指针作为地图的键。这可能有效(在某些方面,映射只是对的容器),但我从未尝试过使用提升序列化。

可以使用 boost 序列化对指针和指针集合持有的对象进行序列化和反序列化。请参阅教程/指针。