假设我有两个POD结构A
和B
具有相同的初始成员序列,但稍后会有一些差异(我知道,这可以通过继承轻松解决)。
struct A {
int x;
uint64_t y;
int z;
};
struct B {
int x;
uint64_t y;
int8_t z;
};
指向struct的指针需要指向intitial成员(§9.2.20[class.mem])。
现在还有两个问题:
两个结构中的共同成员的对齐必须相同吗?即,以下总是如此:
A a;
B b;
assert(offsetof(A, y) == offsetof(B, y));
如果不是:至少如果我将结构放入一个联合,那么这应该成立,因为标准(§9.2.19[class.mem])说
如果标准布局联合包含两个或多个共享公共初始序列的标准布局结构,并且标准布局联合对象当前包含这些标准布局结构中的一个,则允许检查公共初始其中任何一部分。
我在这里添加了一个额外的例子。
struct A {
int x;
uint64_t y;
int z;
};
struct B {
int x;
uint64_t y;
int8_t z;
};
B convertToB(A& a);
void g() {
A a;
// at this point, I cannot rely on offset(A, y) == offset(B, y)
B b = convertToB(a);
// since I do the copy over the union, offset(A, y) == offset(B, y) holds
}
union U {
A asA;
B asB;
};
B convertToB(A& a) {
U u;
// at this point, offset(A, y) == offset(B, y) holds
u.asA = a;
return u.asB;
}
由于我没有机会知道在某个时刻是否会发生关于联合的副本,并且结构必须在任何地方都相同,我声称,offset(A, y) == offset(B, y)
必须保持。
答案 0 :(得分:0)
您可以在此处找到对象成员的观察要求:
9.2 / 13:分配具有相同访问控制的(非联合)类的非静态数据成员,以便以后的成员具有更高的成员 类对象中的地址。非静态分配的顺序 具有不同访问控制的数据成员未指定。 实现对齐要求可能会导致两个相邻成员 不要在对方之后立即分配;可能 管理虚拟功能和虚拟基础的空间要求 类。
在您的struct
中,所有成员都拥有相同的访问权限,因此您可以在此处获得有关订单的保证。
但是请注意引用的最后一句:不能保证两个连续成员之间的空格是相同的(虽然不太可能)。这就是为什么我建议采用union
方法。您不仅可以从标准保证中受益,还可以在源代码中清楚地传达您的意图。
修改强>
我们可以考虑另一个方面:POD类型是一种普通类型,并且具有标准布局。
9.2 / 16:如果两个标准布局结构类型具有相同数量的非静态数据成员且对应,则它们是布局兼容的 非静态数据成员(按声明顺序)具有布局兼容性 类型
3.9 / 11:如果T1和T2两种类型相同,则T1和T2是布局兼容类型。
一旦你的结构在某个时刻发散,你就会发现你没有任何保证。但是我知道这可以保证u.asB
布局与它返回的B
对象兼容。
最后,我希望通过简单的可复制对象找到更实际的保证:
3.9 / 2:对于普通可复制类型T的任何对象(基类子对象除外),对象是否保持有效 类型T的值,构成对象的基础字节可以是 复制到char或unsigned char数组中。如果的内容 将char或unsigned char数组复制回对象中 对象随后应保持其原始值。
我认为可以从中推断出,在你的情况下,在联合中存储一个值但是读取另一个值会起作用。但请注意,根据此(非规范性)注释,这不是一般事实:
9.5 / 4: [注意:通常,必须使用显式析构函数调用和放置新运算符来更改联合的活动成员。 - 后注]