【问题标题】:Object serialization in C++C++ 中的对象序列化
【发布时间】:2015-03-02 17:35:27
【问题描述】:

我想对一些结构化数据进行序列化/反序列化,以便通过char* buffer 将其通过网络发送。

更准确地说,假设我有一条struct Message 类型的消息。

struct Message {
        Header header;
        Address address;
        size_t size; // size of data part
        char* data;
    } message 

在 C 语言中,我会使用如下内容:

  size = sizeof(Header) + sizeof(Address) + sizeof(size_t) + message.size;
  memcpy(buffer, (char *) message, size);

进行序列化,并且

Message m = (Message) buffer;

反序列化。

在 C++ 中“正确”的方法是什么。定义一个类而不是一个结构更好。我应该重载一些运算符吗?是否有对齐问题需要考虑?

编辑:感谢您指出“char *”问题。提供的 C 版本不正确。 data 字段指向的数据部分应单独复制。

【问题讨论】:

  • 是什么阻止你在 C++ 中做同样的事情?除了您似乎没有序列化 data 字段这一事实之外,也不考虑结构填充之类的事情。
  • 您也不会在 C 中通过网络按原样发送该结构。尝试一下,看看你是否没有得到垃圾或段错误。 (如果没有特殊安排,data 中存储的地址在创建它的进程之外没有任何意义。)
  • “在 C 语言中,我会使用诸如...之类的东西。”你会大错特错。 sizeof (struct Message) 可读、可维护并且正确。您的三种尺寸的总和都不是。
  • 在 C 语言中,如果您有一个未知大小的数组 char data[]; 而不是指针 char * data;,则可以这样做,只要对齐和字节排序不影响您。但这在标准 C++ 中并不完全支持。
  • “定义一个类比定义一个结构更好。” - 它们完全一样(除了默认的访问限制)。

标签: c++ oop serialization


【解决方案1】:

其实有很多种口味:

您可以让它为您服务:http://www.boost.org/doc/libs/1_52_0/libs/serialization/doc/tutorial.html

重载流操作符<< 用于序列化和>> 用于反序列化适用于文件和字符串流

您可以指定一个构造函数 Message (const char*) 用于从 char* 构造。

我喜欢反序列化的静态方法,例如:

Message {
  ...
  static bool desirialize (Message& dest, char* source);
}

因为您可以在反序列化时直接捕获错误。

并且您提出的版本是可以的,在应用 cmets 中的修改时会得到尊重。

【讨论】:

  • 我会强烈推荐“让序列化库为你做”路线,除非你有充分的理由不这样做。当您自己滚动时,您必须涵盖很多边缘情况,以致出错的可能性很高。
【解决方案2】:

为什么不在继承树中插入一个虚拟的“NetworkSerializable”类? 'void NetSend(fd socket)' 方法将发送内容(不暴露任何私有数据),如果没有完整的有效消息被反序列化,或者如果有效消息具有已组装,“缓冲区”中未使用的字符数。

它封装了它所属的类内的所有组装/反汇编协议状态变量和其他工具。它还允许从多个流输入缓冲区组装消息。

我不喜欢静态方法。与反序列化相关的协议状态数据应该是每个实例的(线程安全)。

【讨论】:

    猜你喜欢
    • 2012-09-12
    • 2019-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-10
    • 2011-03-12
    • 2015-08-10
    相关资源
    最近更新 更多