POD 结构(相同类型的成员):成员是否位于连续的内存位置?

POD struct (members of same type): are members in contiguous memory locations?

给出

template <typename T>
struct Vector3d { T x, y, z; };

注意:我不介意在 z 之后填充,只要 x、y、z 是连续的

向结构中添加填充的唯一原因 类 是为了满足其成员的对齐要求。请注意,结构的对齐是其成员与最大对齐要求的对齐。结构的大小是其对齐的倍数,添加尾部填充以满足这一点。

由于 Vector3d 的成员属于同一类型,因此已经满足对齐要求,因此,成员之间或结构末尾没有任何填充。

C++ 标准中没有要求无缘无故地插入任意填充。

为了 100% 确定,请输入 static_assert:

static_assert(sizeof(Vector3d<float>) == 3 * sizeof(float), "Unexpected layout.");
static_assert(sizeof(Vector3d<double>) == 3 * sizeof(double), "Unexpected layout.");

有人说 C++ 标准中没有明确说明保证,因此不能依赖它。但是,C++ 标准通常未明确规定,因此需要了解其背后的基本原理。在我个人看来,那些人毫无理由地传播恐惧、不确定和怀疑。

Is it safe to assume that x, y, and z are in contiguous memory locations?

语言在技术上没有这样的保证。

另一方面,它们也没有必要不连续,实际上它们很可能是连续的。

If not is it possible to enforce in a cross-platform way?

确保对象位于连续内存位置的跨平台方式是数组:

template <typename T>
struct Vector3d { T components[3]; };

数组还使使用指针算法迭代对象成为合法的。

Is it safe to assume that x, y, and z are in contiguous memory locations?

标准没有做这样的保证。

但实际上,理智的实现不会在相同类型的相邻字段之间插入任何填充(因为这样的填充永远不需要1)。

如果你想要额外的安全,添加一个static_assert:

static_assert(sizeof(Vector3d<float>) == 3 * sizeof(float));

Is it at least safe to assume that for T = float and T = double?

据我所知,字段类型在这里没有任何区别。


1 — 保证数组不包含填充。由于您可以创建任何类型的数组,因此实现必须能够将任何单一类型的对象彼此相邻存储且没有填充。

不,绝对不能保证相同类型的结构元素之间没有填充,即使是 "large" 普通旧数据类型,例如 double。此外,试图通过指向另一个元素的指针的指针算术到达一个元素的行为是未定义的。

更好写

template <typename T>
struct Vector3d { T t[3]; };

保证连续性和指针运算,并为xyz提供访问函数。

如果您不喜欢调用函数的语法,并且愿意容忍一些最有可能体现在 struct 本身的开销,那么您总是可以绑定引用:

template <typename T>
struct Vector3d
{
    T t[3];
    T& x = t[0];
    T& y = t[1];
    T& z = t[2];
};