【问题标题】:How to serialize an object that keeps pointers to other objects in C++?如何序列化一个在 C++ 中保持指向其他对象的指针的对象?
【发布时间】:2013-09-25 04:12:46
【问题描述】:

我正在寻找一种在 C++ 中序列化大型复杂对象的方法。我一直在考虑使用 boost 序列化 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&lt;SignalData *, float&gt; * preComputedIntegrals 填充了数据。

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

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

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

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

【问题讨论】:

  • 你真的很喜欢他们的指针,不是吗?
  • 这可能是因为我觉得java最舒服,而且一切都是指针,我认为这是一件好事。但在这种情况下,数据总计约 5GB,您希望我按值传递所有内容吗?
  • 我希望您在需要引用对象时通过引用传递。我希望您在需要副本时按值传递。我希望您在需要动态分配时存储智能指针。我希望您在需要对象时存储对象。如果按值传递大型对象让您感到害怕,请阅读thisthisthis

标签: c++ pointers serialization boost


【解决方案1】:

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

answers to this question 详细介绍了您需要做些什么来帮助库在反序列化时识别派生类。

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

另外,boost序列化还可以track your objects为你服务,这样当两个指向同一个对象的指针被序列化时,该对象只被序列化一次。

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

【讨论】:

  • 在这种情况下,另一个地图内有一个地图。所以从某种意义上说,它是一个由 3 个浮点数组成的结构,其中 2 个是键,第三个是值。但是用作键的映射在程序内部的许多其他上下文中使用,它是各种类使用的一种主要数据存储库,因此它不能嵌入其中一个类中,它必须是'只有'被它引用。
  • @NataliaZoń:可以针对您的代码以及似乎过度使用指针的内容制作一些 cmets。在我的回答中,我试图坚持序列化问题。 “难闻的气味”陈述可能会分散该答案的注意力,因此我将该陈述更改为更中性的陈述。
【解决方案2】:

可以使用 boost 序列化来序列化和反序列化由指针和指针集合持有的对象。见Tutorial/Pointers

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    相关资源
    最近更新 更多