一个类是POD从二进制读取它是否足够?

时间:2013-01-11 23:29:11

标签: c++ class

对于客户端/服务器应用程序,我需要发送和接收c ++对象。我不需要相应的类来做任何花哨的事情,但希望获得最大的性能(关于网络流量和计算)。所以我只是简单地将它们作为二进制字符串传输。基本上我希望能够做到以下

//Create original object
MyClass oldObj();

//save to char array
char* save = new char[sizeof(MyClass)];
memcpy(save, &oldObj, sizeof(MyClass));

//Somewhere of course there would be the transfer to the client/server

//Read back from char array
MyClass newObj();
memcpy(&newObj, save, sizeof(MyClass));

我的问题:我的课程需要填写什么才能使其正常工作? 转换到其他应用程序时,Naturaly Pointers作为成员将无法工作。但是我的类被认为是POD(在c ++ 03和/或c ++ 11中)并且没有任何指针或等价物(如STL容器)作为成员是否足够?

4 个答案:

答案 0 :(得分:3)

两台机器都需要:

  1. 具有相同的Endianess(对于int)
  2. 相同的浮点表示(double)
  3. 所有类型的大小相同。
  4. 相同的编译器
  5. 用于构建应用程序的相同标志。
  6. 指针不能很好地转移。
  7. 但是网络将成为这里最慢的部分 与传输成本相比,序列化大多数对象的成本将无关紧要。当然,你的目标越大,成本就越高,但是需要一段时间才能产生凹痕。

    您应该考虑更高的维护成本。

答案 1 :(得分:1)

  

为了让这个工作起作用,我的班级需要完成什么?

  • 它必须没有指针成员,你已经提到过了。
  • 不得包含大小为实现定义的成员,例如int
  • 由于字节顺序不同,它不能有整数成员。
  • 由于表示形式不同,它不得有浮点成员。
  • ......可能更多!

基本上,除了特别受约束的场景外,你不能这样做。您必须选择一个协议并使您的数据符合它,以便安全地通过网络发送。

这不是什么大问题,因为性能会受到网络速度和延迟的限制,而不是符合协议的值所需的操作。

答案 2 :(得分:1)

您对运行的硬件/操作系统有多少控制权?您是在编写超级便携的代码,还是仅在32位和64位x86 Windows上运行[例如]?

要完全“超级可移植”,如上所述,您不能拥有任何形式的“实现定义”大小的对象(例如int,例如可以是16,18,32,36或64位) )。这些项目需要存储为定义数量的字节和顺序,以确保在传输时不会被切断/重新排序。浮点可能更糟......

许多“超级便携”应用程序将其数据存储为文本。它有点慢,但它使它简单易用,因为文本只是一个字节流,无论你运行它的架构,它的排序方式与你使用的任何机器相同(只要你坚持0-9,A- Za-z,!?<>,。()*&和其他一些字符 - 并提防EBCDIC编码的机器,但它们倾向于处理“ascii-to-ebcdic”转换。另一端只需要将文本转换回字符串/整数/浮点数/双精度数,无论你需要什么。从整数到数字串的转换每个数字需要一个除法(使用十六进制或基数-36使得它更好一些,但使人类可读性更低 - 有时是好事,有时是坏事)。这显然比存储4个字节慢。另一个缺点是它(取决于使用的值)通常更长时间来存储文本中的数字而不是二进制数字。所以你的网络数据包会有点大。这将比转换产生更大的影响,因为处理器可以在使用10Gbit网卡发送1KB所需的时间内进行大量数学计算。当然,你需要一些额外的字节(空格,逗号,换行符或其他任何东西),这样你就能分辨出一个数字123456和三个12,34,56之间的区别。[当然,不需要使用“ ,“每个之间”。而且一旦到达,你需要一些代码来解析另一端的整个事物。

如果你知道你的系统总是有32位整数和IEEE-754浮点数[这些非常常见!],那么你可能会担心字节顺序。如果你知道它总是在“x86”或类似的东西上,你也不必担心字节顺序。但是,当您决定“在iphone上运行我的代码是个好主意”时,您现在可能需要修改代码。当然,您可以将其留在iphone方面以符合其他要求。

答案 3 :(得分:-4)

其他答案提到了为此目的如何使用class。就个人而言,我更喜欢使用struct。在C ++中,struct可以像class一样拥有成员方法/运算符,构造函数/析构函数,支持继承等。但是,struct具有定义明确且可预测的内存布局,并且可以通过#pragma语句明确对齐该布局以添加/删除编译器的隐式填充(我从未尝试对齐{{1}之前,但我认为它是支持的)。对于必须在应用程序进程外交换的数据,我总是使用8位对齐的class。出于所有意图和目的,在现代编译器中,struct基本上与struct相同,只是其成员的默认可见性为class而不是public。但我希望将privatestruct分开以用于不同目的。 class只是一个原始的数据容器,您可以自由地处理,在内存中覆盖等。struct是一个对象,其内存布局和填充是编译器定义的,不应该混淆。