c++ - 继承中的内存对齐规则
问题描述
我试图弄清楚在继承的情况下类对齐是如何工作的。目前我明白
- 该类将与其最广泛的成员对齐
- 如果它在数组中,则可以根据其对齐方式填充类的末尾
- 结构成员根据结构对齐方式对齐
例如:
struct Nested { // Due to the long long element it is 8 aligned
short int ShortNestedElement; //6 bytes of padding here
long long int LongNestedElement;
};
struct Example {
short int ExampleMember_1; // 6 bytes of padding here
Nested ExampleMember_2;
char ExampleMember_2; // 7 bytes of padding here
};
我的困惑来自于继承:
struct Base1 {
short unsigned int Base_1Member_1;
long unsigned int Base_1Member_2;
};
struct Base2 {
unsigned int Base_2Member_1;
};
struct Base4 {
unsigned int Base_4Member_1;
};
struct Base3 : Base4 {
long unsigned int Base_3Member_1;
};
struct Final: Base1, Base2, Base3 {
};
根据 clang 类 Final 的布局是:
*** Dumping AST Record Layout
0 | struct Final
0 | struct Base1 (base)
0 | unsigned short Base_1Member_1
8 | unsigned long Base_1Member_2
16 | struct Base2 (base)
16 | unsigned int Base_2Member_1
24 | struct Base3 (base) --------> ?
24 | struct Base4 (base)
24 | unsigned int Base_4Member_1
32 | unsigned long Base_3Member_1
| [sizeof=40, dsize=40, align=8,
| nvsize=40, nvalign=8]
我不明白为什么,当我们考虑 Base3 时,即使它继承自 Base4(因此 Base4 的成员位于 Base3 之前),我们会考虑 Base3(8) 而不是 Base4(4) 的对齐方式。但是,如果我更改这两个类的内容,使 Base3 与 4 对齐,Base4 与 8 对齐,则需要 Base4 对齐。
它是继承层次结构中最广泛的类吗?
解决方案
这在很大程度上取决于实现。在您的代码中:
struct Nested { // Due to the long long element it is 8 aligned short int ShortNestedElement; //6 bytes of padding here long long int LongNestedElement; }; struct Example { short int ExampleMember_1; // 6 bytes of padding here Nested ExampleMember_2; char ExampleMember_2; // 7 bytes of padding here };
long long
不必是 8 个字节,short
不必是 2 个字节,char
也不必是 1 个字节。如果是,则long long
不必是 8 字节对齐的,short
不必是 2 字节对齐的,char
也不必是 1 字节对齐的。也不保证按照您的评论指示插入填充。这些都是实现定义的。
现在让我们看看你的问题:
struct Base1 { short unsigned int Base_1Member_1; long unsigned int Base_1Member_2; }; struct Base2 { unsigned int Base_2Member_1; }; struct Base4 { unsigned int Base_4Member_1; }; struct Base3 : Base4 { long unsigned int Base_3Member_1; }; struct Final: Base1, Base2, Base3 { };
我不明白为什么,当我们考虑 Base3 时,即使它继承自 Base4(因此 Base4 的成员在 Base3 之前),我们会考虑 Base3(8) 而不是 Base4(4) 的对齐方式。但是,如果我更改这两个类的内容,使 Base3 与 4 对齐,Base4 与 8 对齐,则需要 Base4 对齐。
如果Base3
继承自Base4
,则Base4
是 的子对象Base3
,因此 的对齐要求Base4
有效地传播到Base3
。因此,alignof(Base3)
成为其成员的较大的alignof(Base4)
和对齐的要求。因此,实际上,它占据了“层次结构中最广泛的”。至少,现实世界的对齐方式就是这样。
同样,该标准没有指定这类事情。不能保证alignof(Base3) == std::max(alignof(Base4), alignof(unsigned long))
。
以后在讨论对齐的时候,请使用alignas
而不是依赖内置类型的对齐。
推荐阅读
- python - 在 PyArray_ResolveWritebackIfCopy() 之前更新 numpy 数组 pre 1.14
- php - 将 JSON 数组传递给 http_build_query
- c++ - 未定义的引用 - 将 2 个字符串调用到一个函数中
- python - 如何在 Python 中消除导致列表错误的项目
- oauth-2.0 - 将数据推送回 Auth0 数据库
- vba - vba 测试列中的单元格,仅以逗号的任何顺序列出单词
- java - Selenium(Java) - 从 csv 或 txt 文件获取 URL 以打开 WebDriver
- python - Python - 为不同的列聚合两行不同的操作
- python - Django 多文件上传
- python - Cygwin 在哪里安装 python 包?