C++ - 对象填充的复杂性

C++ - object padding intricacies

我试图深入理解结构和 class 填充,因此我设计了一个我认为比我在有关该主题的教程中找到的许多示例更具挑战性的示例。我在 x64 机器上用 g++ 编译了它,没有启用任何代码优化。我的代码如下:

class Example
{
    private:
        long double foobar;     // 10 bytes + 6 padded bytes as double follows
        double barfoo;          // 8 bytes + 8 padded bytes
        static float barbar;    // didn't count as it's a static member
        float *fooputs;         // 8 bytes + 8 padded bytes
        int footsa;             // 4 bytes, stored in the padded portion of float
        char foo;               // 1 byte, stored in the padded portion of float

    public:
        int function1(int foo) { return 1; }
        void function2(int bar) { foobar = bar; }
};

int main()
{
    std::cout << sizeof(Example) << std::endl;   // 48 bytes
    return 0;
}

虽然我看到 Example 的大小是 48 字节,但我预计它是 37 字节。我的期望论证如下:

由于结果与预期不同,我试图通过注释 class 成员来了解 C++ 如何将 Example 的大小评估为 48 字节。因此,除了 foobar 的论证之外,我假设了我在每个成员的内联评论中所写的理由。

谁能解释一下如何将大小计算为 48 字节,我的理由是否正确?

你忘记了最后的填充sizeof returns 个 number of bytes between two adjacent members in an array。在您的情况下,alignof(long double) 很可能是 16,因此每个 Example 实例都需要位于 16 字节对齐的地址。

因此,如果您在 16 字节对齐地址 A 处有第一个 Example 实例,然后成员需要 37 个字节,则下一个 Example实例不能存放在A+37字节,需要存放在A+k * 16。满足 k * 16 >= 37 的最小可能 k 是 3。这最终给了你字节数在数组 3 * 16 = 48 中的两个 Example 实例之间,正好是 sizeof(Example).