C++ 将原始数据作为对象访问

问题描述 投票:0回答:1

我正在使用一个库,它将 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字节)?

c++ arrays class memory-alignment
1个回答
0
投票

即使对齐和尺寸正确,从技术上讲仍然是符合标准的 UB。您不能强制转换为某种类型的对象(此处为

Vector3
),假装它从未显式或隐式创建时存在。实际上,编译器可能不会太在意。

对于对齐本身:

Vector3
的对齐要求在技术上可能比
double
更大,因此
GetFromLibrary
返回的指针可能会错位。这可以在您所依赖的 ABI 规范中查找或通过添加
static_assert(alignof(Vector3) <= alignof(double));
来查找。然而,我不认为任何常用的 ABI 都能做到这一点。

对于其他布局问题:从技术上讲,

Vector3
的末尾可以有填充。然而,我再次强调,我不知道有任何 ABI 具有这样的行为。

© www.soinside.com 2019 - 2024. All rights reserved.