为结构成员分配的内存是连续的吗?如果struct成员是数组呢?
Is the memory allocated for struct members continguous? What if a struct member is an array?
假设我在C/c++中定义了一个名为test
的简单结构体,如下所示。
struct test
{
double height;
int age;
char gender;
}
对于这个结构体的特定实例,说test A
是A.height, A.age, A.gender
连续的在内存中?
更一般地说,数组结构体和结构体数组在内存中的布局是怎样的?照片会很有帮助的。
它们在内存中不一定是连续的。这是由于结构体填充。
但是,在您的特殊情况下,它很可能是连续的。但是如果你把顺序改成这样:
struct test
{
char gender;
int age;
double height;
}
那么他们很可能不会。但是,在您的特殊情况下,您仍然可能在gender
之后获得填充,以将结构体重新对齐为8字节。
SoA (Struct of Arrays)和AoS (Array of Structs)之间的区别是这样的:
SoA:-----------------------------------------------------------------------------------
| double | double | double | *pad* | int | int | int | *pad* | char | char | char |
-----------------------------------------------------------------------------------
《超能:
-----------------------------------------------------------------------------------
| double | int | char | *pad* | double | int | char | *pad* | double | int | char |
-----------------------------------------------------------------------------------
请注意,每个结构中都有AoS。而SoA填充在数组之间。
它们有以下权衡:
- AoS对于程序员来说更容易读,因为每个"对象"都放在一起。
- AoS可能有更好的缓存局域性,如果所有的结构体成员被一起访问。
- SoA可能更有效,因为将相同的数据类型分组在一起有时会暴露向量化。
- 在许多情况下SoA使用更少的内存,因为填充只是在数组之间,而不是在每个结构体之间。
各个字段是连续的,因为它们之间不会存储其他变量。它们也保证按照您声明的顺序存储。但是编译器可以自由地在各个字段之间插入填充,例如,将内容与单词边界对齐。所以如下:
struct test
{
double height;
char gender;
int age;
};
在内存中可能看起来像这样:
+7 +6 +5 +4 +3 +2 +1 +0
+---+---+---+---+---+---+---+---+
0x0000 | height |
+---+---+---+---+---+---+---+---+
0x0008 | age | |gen|
+---+---+---+---+---+---+---+---+
至于SoA和aop之间的区别,它们的布局与您想象的完全一样。
除了标准的免责声明"这取决于你的平台,编译器,等等"…是的,height
, age
和gender
将在内存中连续,中间没有填充:
height|age|gender
然而,如果你有一个test
的数组,每个数组元素在gender
之后都有填充,以便下一个元素的height
正确对齐。
|height0|age0|gender0|padding0|height1|age1|gender1|padding1|...
如果你的目标是使用尽可能少的内存,那么你应该使用"数组结构",因为它不使用填充。
|height0|height1|...
|age0|age1|...
|gender0|gender1|...
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 如果基类包含双指针成员,则派生类的构造函数
- int数据类型的指针指向的是什么,如果是一个类的私有数据成员,我们创建了该类的两个对象?
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 提升精神 x3 解析为结构,如果它为空,则跳过成员
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 如果参数与数据成员的参数同名,该怎么办?
- 在C++中,如果成员引用在其声明中初始化,为什么需要存储空间?
- 检查私有成员变量是否在一定范围内,如果没有调整
- C++类析构函数删除成员(如果"owner"?
- 如果我必须覆盖非虚拟成员函数怎么办
- 如果模板中存在成员函数指针,如何获取该指针
- 如果函数是在类的主体中定义的,我是否需要在成员函数的返回类型中指定 typename?
- 如果类在 C++ 中具有常量或引用类型的非静态数据成员,为什么编译器不提供默认赋值运算符?
- 如果包含引用成员的类中缺少原始变量,为什么它仍然可以访问?
- 如果类的成员,C++数组会导致崩溃
- 如果基类指针无法访问派生类成员函数,那么多态性有什么方便的呢?
- 如何将超类的受保护成员访问到其派生类. 如果已在派生类中声明了具有相同名称的函数?
- type_trait 的有成员 如果使用全局函数则失败
- 如何仅设置成员(如果存在)