我正在使用一个库,它将 3D 笛卡尔向量数组表示为
double
的连续一维数组,其中三个后续条目对应于一个向量的笛卡尔分量。我还有一个自写的 3D 向量类 Vector3
,它实现了一些算术。我想将这个普通的 double
数组视为 Vector3
对象数组,如下所示:
class Vector3 {
// Some functions and operators
double m_pData[3]; // the components of the vector
};
double *pd = GetFromLibrary(); // The input raw data
Vector3 *pv = (Vector3*)pd; // Treat raw data as array of objects...
pv[3].m_pData[1] = 17.5; // Set the Y component of the fourth vector
我在几个不同的编译器和平台上尝试了这段代码,它工作得很好。从天真的角度来看,它当然应该总是有效,但我不确定是否会出现任何对齐问题。 C++ 标准是否规定这是允许的?如果没有,有什么方法可以修改代码以使其符合标准,而无需将数据复制到不同的内存位置?
或者以不同的方式提问:标准是否保证
Vector3
的普通数组拥有其所有 double
数据成员而没有间隙,我们是否会发生编译器插入一些填充以进行对齐(可能是32字节)?
即使对齐和尺寸正确,从技术上讲仍然是符合标准的 UB。您不能强制转换为某种类型的对象(此处为
Vector3
),假装它从未显式或隐式创建时存在。实际上,编译器可能不会太在意。
对于对齐本身:
Vector3
的对齐要求在技术上可能比double
更大,因此GetFromLibrary
返回的指针可能会错位。这可以在您所依赖的 ABI 规范中查找或通过添加 static_assert(alignof(Vector3) <= alignof(double));
来查找。然而,我不认为任何常用的 ABI 都能做到这一点。
对于其他布局问题:从技术上讲,
Vector3
的末尾可以有填充。然而,我再次强调,我不知道有任何 ABI 具有这样的行为。