简体   繁体   English

对于应该在C ++中保存结构的缓冲区,使用正确的对齐方式

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

Suppose we have some struct, say 假设我们有一些结构,比方说

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

Such a struct should typically have an alignment of 8, as the size of its largest contained type is 8. 这样的结构通常应该具有8的对齐,因为其最大包含类型的大小是8。

Now imagine we want to declare a placeholder struct to hold the value of S : 现在假设我们要声明一个占位符结构来保存S的值:

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

Now we want to place it inside of another class: 现在我们想把它放在另一个类中:

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(); }
};

Problem is, Placeholder is now aligned incorrectly within User . 问题是, Placeholder现在在User对齐不正确。 Since the compiler knows that Placeholder is made of chars, not doubles, it would typically use an alignment of 1. 由于编译器知道Placeholder由字符而不是双字符组成,因此它通常使用1的对齐方式。

Is there a way to declare Placeholder with the alignment matching that of S in C++03? 有没有办法声明Placeholder与C ++ 03中的S匹配? Note that S is not a POD type. 请注意, S不是POD类型。 I also understand C++11 has alignas , but this is not universally available yet, so I'd rather not count on it if possible. 我也理解C ++ 11有alignas ,但这还没有普遍可用,所以如果可能的话我宁愿不依赖它。

Update : just to clarify, this should work for any S - we don't know what it contains. 更新 :只是为了澄清,这应该适用于任何S - 我们不知道它包含什么。

You can use a union , if you can make S conform to the requirements of being a member of a union *. 您可以使用一个union ,如果你可以让S符合成为一名成员的要求union *。

A union is guaranteed to have enough storage for its largest member, and aligned for its most reastrictive member. union保证为其最大的成员提供足够的存储空间,并为其最重要的成员进行调整。 So if we make the placeholder a union of both the raw char buffer and all the types that will actually be stored there, you will have sufficient size and correct alignment. 因此,如果我们使占位符成为原始字符缓冲区和实际存储在那里的所有类型的并集,那么您将具有足够的大小和正确的对齐方式。

We will never access the members of the union other than the storage itself. 除了存储本身,我们永远不会访问union成员。 They are present only for alignment. 它们仅用于对齐。

Something along these lines: 这些方面的东西:

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

  • " requirements of being a member of a union " : Members of union s cannot have: non-trivial constructor, non-trivial copy constructor, non-trivial destructor, non-trivial copy-assignment operator. 身为工会成员要求 ”:成员union s不能有:非平凡的构造函数,不平凡的拷贝构造函数,非平凡的析构函数,非平凡的拷贝赋值运算符。

I believe that boost::aligned_storage may be exactly what you're looking for. 我相信boost::aligned_storage可能正是你想要的。 It uses the union trick in such a way that your type doesn't matter (you just use sizeof(YourType) to tell it how to align) to make sure the alignment works out properly. 它使用联合技巧,使您的类型无关紧要(您只需使用sizeof(YourType)告诉它如何对齐)以确保正确对齐。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM