为什么编译器会抱怨对齐?

Jan*_*ard 10 c++ compiler-construction alignment compiler-warnings visual-c++

我想更多地了解对齐方式.为什么Microsoft编译器(Visual Studio 2012 Express)会抱怨以下代码片段的对齐方式?

__declspec(align(16)) class Foo
{
public:
    virtual ~Foo() {}
    virtual void bar() = 0;
};
Run Code Online (Sandbox Code Playgroud)

这是编译器向我提出的警告:

warning C4324: 'Foo' : structure was padded due to __declspec(align())
Run Code Online (Sandbox Code Playgroud)

这个类是否有任何虚拟方法甚至无关紧要.即使对于空类,编译器也会使用相同的警告消息进行抱怨.空类是如何对齐的?编译器如何填充此类?

cel*_*chk 16

警告并不一定意味着您做错了什么,但告诉您可能没有打算这样做.请注意,允许编译器警告开发人员认为值得警告的任何内容.原则上,你也可以在13日星期五被警告编译.

在这种特定情况下,假设可能是当您指定对齐时,您不希望使类更大.因此,如果由于你给出的对齐要求而使类变得更大,那么你犯错误的可能性并不大.

当然,这就留下了为什么对齐要求使类更大的问题.现在我们回到了标准领域(虽然它__declspec本身是微软的扩展,而不是标准).C++标准要求在数组中,对象彼此跟随,其间没有任何空间.因此,如果对象必须与16字节边界对齐,则对象的大小必须是16的倍数.如果成员的大小(显式和隐式)都没有给出必要的大小,则编译器必须将未使用的字节添加到对象.这些字节称为填充.请注意,即使在不是数组成员的对象中也存在此填充.

现在你的类只包含一个隐式虚拟指针(因为它包含虚函数),根据体系结构,它可能是4或8字节大.由于您已请求16字节对齐,因此编译器必须添加12或8字节的填充以使大小为16的倍数,如果没有手动对齐规范,则不必添加.这就是编译器警告的内容.

  • 应该完全有一个警告:你今天早上9点开始,现在是晚上8点.得到一些奇怪的食物,你是一个低血糖的阴霾,你的代码是无稽之谈 (12认同)