是否可以简单地序列化C ++对象

时间:2014-03-04 20:57:20

标签: c++ c serialization struct

您可以将对象强制转换为十六进制数据字符串(类似于数据包的发送方式)然后将其存储然后再将对象转换回来吗?我知道C语言结构可能是C ++中的基本对象。

不同系统的序列化兼容性并不重要。

auto obj = new Something();

auto objHex = (unsigned char*) obj;

// store objHex in like a db
// retrieve objHex

auto obj2 = new Something();  // allocate
*obj2 = (Something*) objHex;  // set the dereference

4 个答案:

答案 0 :(得分:4)

没有。原因:
a)动态分配的内存,即。 struct / class中的指针 b)结构的Endianess,int-size,padding等,成员的顺序......

其他事项:
“如果”有可能,则没有理由创建一个完整的对象
在覆盖它之前使用构造函数调用 在我看来,你过度使用汽车。

答案 1 :(得分:4)

这并不容易(并且通常不会自动执行),但像s11n这样的库可能会有所帮助。

我会考虑一些文字serialization格式,如JSON,例如jsoncppYaml。当然,你需要编写一些代码。

pasztorpisti所述,您可以考虑从C ++声明中获取一些代码。也许MELT可能对您有所帮助(您可以使用它自定义g++以“提供有关程序类型的反映信息”,根据pasztopisti的说法)。但这需要数周的工作。

顺便说一句,难题是如何处理指针,特别是指向共享同一个尖头对象的指针,以及指向代码的指针。也许对于您的特定应用程序,事情可能会更简单。另请阅读garbage collectionpersistence;两者都有共同关注的问题。

在开始设计应用程序时,可以尽早思考IMHO持久性和序列化。之后可能很难添加。

答案 2 :(得分:0)

  

可以将对象转换为十六进制数据字符串(类似于数据包的方式)   发送)然后存储然后再将对象投射回去?

没有。
(或许我不知道怎么做。)

注意 - tcp数据包不是十六进制或其他格式化。

将指针强制转换为数据缓冲区对数据没有任何作用,对字节数组的二进制内容没有任何作用。没有转换。没有格式化。

因此,c样式转换为(unsigned char *)将 NOT 将内容转换为十六进制文本。

如果要转换为十六进制格式,则必须编写代码(ieoperator>>()和operator<<())将每个字节转换为两个字符。这很容易但处理器很贵。 (你可以在网上找到很多例子。)


  

是否可以简单地序列化C ++对象

许多人会强调你的问题中的'序列化',并担心字符串和其他问题。 'Serialize'在某些情况下具有特定含义 - 持久存储是我第一次遇到这些项目的地方。

另一方面,如果二进制文件没问题,并且您只想向/从文件系统或通过tcp / ip套接字流发送二进制数据包,您只需要使用write / read来存储/将对象的数据检入/输出(二进制)文件,或通过流套接字发送/接收。

请考虑以下事项:

 class Something
 {
 public:
    Something(void)   { clear(); }
    ~Something (void) { clear(); }

    void clear(void){for (int i=0; i<100; i+=1) m_data[i] = 0;}

    void init(void) {for (int i=0; i<100; i+=1) m_data[i] = char(i); }

    const char* data_GetAddr() { return m_data; }
    char*       data_PutAddr() { return m_data; }

    // show 3 bytes:
    void show(void) { std::cout << "m_data: "
                                << m_data[0] << "  "
                                << m_data[1] << "  "
                                << m_data[2] << "\n"
                                << std::endl;  }   
 private:
    char  m_data[100];
    // and various other POD here
 };



 int main (int, char**)
 {
    auto obj1 = new Something();
    obj1->init();
    obj1->show(); // show initialized data

    // cast does not convert from binary to text
    // so the following does not help
    // auto obj1Hex = (unsigned char*)obj1; 

    // but we can store obj1 to a file in binary
    std::stringstream ss;                        // a ram-base 'file'

    // store data to file using write.
    ss.write(obj1->data_GetAddr(), sizeof(Something));

    // now we allocate a receive buffer just as you have suggested
    auto obj2 = new Something();  // allocate space for another instance
    obj2->show();  // show this has 0's

    // retrieve obj data from file, installing it into obj2 working buffer.
    ss.read(obj2->data_PutAddr(), sizeof(Something));

    obj2->show();       // show results

    return(0);
 }

输出类似于以下内容(emacs将二进制0,1,2显示为实现它们所需的击键,即control- @,control-A,control-B

m_data:^ @ ^ A ^ B&lt;&lt;&lt; init()

之后的obj1

m_data:^ @ ^ @ ^ @&lt;&lt;&lt;未初始化的obj2(全0)

m_data:^ @ ^ A ^ B&lt;&lt;&lt;读取后的obj2,没有init()

答案 3 :(得分:0)

如果您只是想将C ++中的对象序列化为二进制blob数据,JSON或XML,您可以查看序列化库,例如cereal或{{3 }}

如果您需要支持原始指针或引用,Boost是可行的方法。如果你不需要序列化指向事物的原始指针,而是使用C ++ 11风格的智能指针或根本没有指针,我建议使用谷歌,因为它支持标准库中的几乎所有东西,而Boost有一个更有限的子集。