对缓冲区使用正确的对齐方式,该缓冲区应该容纳C++中的结构

Use the right alignment for a buffer which is supposed to hold a struct in C++

本文关键字:缓冲区 C++ 结构 方式 对齐      更新时间:2023-10-16

假设我们有一些结构,比如

struct S
{
  double a, b;
  ~S(); // S doesn't have to be POD
};

这样的结构通常应该具有8的对齐方式,因为它包含的最大类型的大小是8。

现在假设我们想要声明一个占位符结构来保存S:的值

struct Placeholder
{
  char bytes[ sizeof( S ) ];
};

现在我们想把它放在另一个类中:

class User
{
  char someChar;
  Placeholder holder;
public:
  // Don't mind that this is hacky -- this just shows a possible use but
  // that's not the point of the question
  User() { new ( holder.bytes ) S; }
  ~User() {  ( ( S * )( holder.bytes ) )->~S(); }
};

问题是,Placeholder现在在User中未正确对齐。由于编译器知道Placeholder是由字符组成的,而不是双字符,因此它通常会使用1的对齐方式。

有没有一种方法可以用与C++03中S的对齐方式匹配的对齐方式来声明Placeholder?请注意,S不是POD类型。我也知道C++11有alignas,但这还不是普遍可用的,所以如果可能的话,我宁愿不指望它。

更新:只是澄清一下,这应该适用于任何S——我们不知道它包含什么。

如果可以使S符合成为union*成员的要求,则可以使用union

union保证为其最大成员提供足够的存储空间,并为其最合理的成员进行对齐。因此,如果我们将占位符设为原始字符缓冲区和实际存储在那里的所有类型的并集,那么您将拥有足够的大小和正确的对齐方式。

除了存储器本身,我们永远不会访问union的成员。它们仅用于对齐。

大致如下:

struct Placeholder
{
  union
  {
    char bytes [sizeof(S)];
    double alignDouble;
  };
};

  • "作为联合成员的要求":union的成员不能具有:非平凡构造函数、非平凡复制构造函数、非琐碎析构函数、非平凡副本赋值运算符

我相信boost::aligned_storage可能正是您想要的。它使用并集技巧的方式是,你的类型无关紧要(你只需要使用sizeof(YourType)来告诉它如何对齐),以确保对齐正确。