确保std::string正确对齐

Assure correct alignment on std::string

本文关键字:对齐 string std 确保      更新时间:2023-10-16

编译此标头:

// myheader.h
class MyClass {
    MyClass();
    ~MyClass();
    unsigned int mMyUint;
    bool bMyBool;
    std::string sMyString;
};

使用Visual Studio 2010/W4(我被告知要这样做),目标x64给了我以下warning C4121:

'MyClass' : alignment of a member was sensitive to packing,指的是std::string sMyString所在的行。微软的官方帮助建议使用#pragma pack(x),其中x是1、2、4,取决于在其结构/类中使用的成员。

不,我想知道std::string使用哪种对齐方式?我的想法是std::string和编译器都不是独立于平台的。有没有办法解决这个问题,特别是考虑到其他可能有任何其他结盟的成员?

最好是一个独立于编译器的(甚至是可移植的)解决方案。

更新:关于jalf提供的非常有用的答案:不,在这个文件中,我没有使用#pragma pack(x)。我在另一个结构中使用了它,在那里我使用了位字段,我看到这些字段在不使用#pragma pack(x)时被填充。现在,我只是被同样的陷阱吓了一跳,因为我不知道Microsoft编译器是如何解析std::string的。

独立于编译器且可移植的解决方案正是您向我们展示的代码。如果您不做任何破坏它的事情,编译器会负责正确对齐所有内容。(例如使用需要特殊对齐的SIMD类型,或使用#pragma pack

如果您使用的是#pragma pack,那么:

  1. 你为什么不给我们看
  2. 不要

如果您在/W4上向我们显示的代码给您任何警告,请归咎于Microsoft。该代码正确、可移植且安全(使用pack杂注的代码不同)。

微软对/W4上的警告有一些奇怪的想法。大多数编译器只对看起来可能包含错误的内容发出警告。

微软有一大堆警告,基本上是说"我没有理由怀疑这段代码有问题,但如果你用不同的方式编写,它可能会包含一个错误",这纯属无稽之谈。

对于其他编译器,我通常建议在启用所有警告的情况下进行编译。在微软的编译器上,这是不可行的。(尽管您可以使用/W4,并选择性地静音特定的无意义警告)

认为他们特别告诉你的是,该结构包含填充字节(因此,如果确实使用了#pragma pack,它将更改类的布局,并且受影响的类成员之一将对此更改"敏感")。

如果可能的话,考虑重新排列类成员,使它们按大小降序排列。这样可以提供更紧凑的类布局,只在类的末尾添加填充(如果有的话)。

但是您当前使用的类定义没有任何错误。