【问题标题】:Size of object and C++ standard对象大小和 C++ 标准
【发布时间】:2022-01-23 17:38:25
【问题描述】:

环顾四周,我发现很多地方都解释了获取某个对象(类或结构)大小的方法。我读到了填充,关于虚函数表影响大小以及“纯方法”对象的大小为 1 个字节的事实。但是我找不到这些是关于实现的事实还是 C++ 标准的事实(至少我无法找到所有这些事实)。

特别是我处于以下情况:我正在处理一些在某些对象中编码的数据。这些对象持有指向其他数据的指针。它们不从任何其他类继承,但它们有一些方法(非虚拟)。我必须将这些数据放在缓冲区中以通过某个套接字发送它们。现在阅读我上面提到的内容,我只是将我的对象复制到发送缓冲区,注意到数据已正确“序列化”,即对象的每个成员都被复制,方法不会影响字节结构。

我想知道我得到的只是因为编译器的实现还是标准规定的。

【问题讨论】:

  • 在此处阅读有关序列化的更多信息; isocpp.org/wiki/faq/serialization。请注意,当您在“另一端”收到数据时,将其转换为对象指针不会产生对象实例(不调用 new),并且您将没有有效的对象。您需要创建一个可以使用数据创建有效实例的构造函数。 (你也可以看看 C++20 的 bitcast)
  • Objects and alignment 讨论了对齐和填充(稍微),并在底部有参考。根据您的数据是什么,对齐和填充可能在整个系统中保持不变,或者它们可能不同。使用指定位宽整数比使用实现定义的类型(如intlong)更安全。不同的架构将表示具有不同字节序的多字节整数。等等。我正在研究的微控制器具有 32 位最大对齐,因此 64 位数字是 32 位对齐的。
  • 在不知道如何将来自对象的数据编码到通过套接字发送的缓冲区的情况下,这是不可能的。这不仅仅是关于 vtables(标准不需要,顺便说一句,即使大多数现代编译器在具有虚函数的 class/struct 类型中使用它们)或填充。这是关于您所做的任何假设,这些假设可能并非在所有编译器上都普遍适用(例如,int 的大小、字节序、浮点格式等)。
  • 您可以简单地发送描述对象的 JSON,然后另一端读取数据的语言无关紧要。由语言来确定 JSON 所陈述的内容,并从中创建相关对象。

标签: c++ object serialization


【解决方案1】:

类的内存布局在 C++ 标准中没有明确规定。甚至没有指定标量对象(例如整数)的内存布局。它们由语言实现来决定,并且通常取决于底层硬件。该标准确实指定了实现特定布局必须满足的限制。

如果一个类型可以简单地复制,那么可以通过将其内存复制到缓冲区来“序列化”它,并且可以按照您的描述将其反序列化。但是,这种简单的序列化仅在反序列化的进程使用相同的内存布局时才有效。通常不能假设是这种情况,因为其他进程可能在完全不同的硬件上运行,并且可能已使用不同(版本)的编译器进行编译。

【讨论】:

  • 非常感谢。好吧,“反序列化”对我来说并不重要,因为在接收端数据可能以不同的方式更方便地封装。
【解决方案2】:

您应该使用 POD(普通旧数据)。如果一个结构没有虚拟表、一些构造函数、私有方法和许多其他东西,它就是 POD。 保证 pod 数据按声明顺序放置在内存中。 pod 数据中存在对齐。你应该指定正确的对齐方式(这是你的决定)。请参阅#pragma pack(推,???)。

【讨论】:

  • 虽然对齐是“您的决定”,但您最好决定使用一个值,该值是您期望它运行的所有平台的最低公分母的倍数。 (某些平台会在未原生对齐的数据上出错。
猜你喜欢
  • 2022-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
相关资源
最近更新 更多