我有整数值,用于访问不相关的数据存储中的数据,即句柄。我已选择将整数包装在结构中以便具有强类型对象,以便不能混合不同的整数。他们是,而且必须是POD。这就是我正在使用的:
struct Mesh {
int handle;
};
struct Texture {
int handle;
};
我有这些句柄的数组,例如: Texture* textureHandles;
。
有时我需要传递一个句柄数组作为 int*
更通用的代码部分。现在我正在使用:
int* handles = &textureHandles->handle;
它基本上采用指向结构的第一个元素的指针并将其解释为数组。
我的问题基本上是这是合法的,还是违反了操纵的严格别名 int* handles
和 Texture* textureHandles
指着同样的记忆。我认为这应该被允许,因为基础类型(int
在两种情况下都以相同的方式访问。我的保留与我通过获取一个结构中的成员的地址来访问多个结构的事实有关。
作为我的第一个问题的延伸,以下是否可以?
int* handles = reinterpret_cast<int*>(textureHandles);
reinterpret_cast<int*>(textureHandles)
绝对是一样好 &textureHandles->handle
。标准中有一个特殊的例外,它继承自C even,它表示指向适当转换的标准布局结构的指针指向该结构的初始成员,反之亦然。
使用它来修改句柄也没关系。它不违反别名规则,因为您使用的是左值类型 int
修改类型的子对象 int
。
递增结果指针,并使用它来访问数组中的其他元素 Texture
但是,对象有点不确定。 Jerry Coffin已经指出有可能 sizeof(Texture) > sizeof(int)
。即使 sizeof(Texture) == sizeof(int)
但是,指针算法仅定义为指向数组的指针(其中任意对象可被视为长度为1的数组)。你没有一个数组 int
在任何地方,所以添加只是未定义。
不,这不能保证有效。特别是,允许编译器在结构的任何元素之后插入填充,但不允许在数组的元素之间插入填充。
也就是说,只有一个元素的结构(类型 int
或者至少与某些东西一样大的东西,比如 long
),大多数编译器都不会插入任何填充的机会非常好,所以你当前的用法可能就是这样 相当 安全作为一般规则。
它当然违反了严格的别名,如果该功能可以访问
阵列都通过 int*
和a Mesh*
或者a Texture*
, 你可以
很好地遇到了问题(虽然可能只有它修改了
以某种方式的数组)。
从你对问题的描述,我不认为是规则
严格的别名确实是你所关心的。真正的问题
是编译器是否可以向不是的结构添加填充
出现在 int
, 以便 sizeof( Mesh ) > sizeof( int )
。和
虽然答案是正式的,我无法想象一个编译器会
这样做,至少在今天,至少在 int
或更大的类型
struct
。 (一个字处理机器可能会添加填充到一个
struct
其中只包含 char
。)
真正的问题可能更多的是通用代码是否
遗产,不能改变或不改变。否则,明显的解决方案
是创建一个通用的句柄类型:
struct Handle
{
int handle;
};
然后从中派生你的类型,或使用 reinterpret_cast
如你所愿。有(或至少是)允许的保证
访问某个成员 struct
通过指向不同的指针
struct,只要成员和所有前面的成员都相同。
这就是你如何模拟C中的继承。即使是保证
已被删除 - 这是它在C ++中出现的唯一原因
出于C兼容性的原因 - 编译器不敢违反
它,考虑到依赖它的现有软件的数量。 (该
例如,Python的实现。几乎所有的Python
插件,包括用C ++编写的插件。)