假设我有两种类型 A 和 B。
然后我做这个类型
struct Pair{
A a;
B b;
};
现在我有这样的功能。
void function(Pair& pair);
并假设 function
只会使用该对的 a
部分。
那么这样使用调用函数是不是未定义行为?
A a;
function(reinterpret_cast<Pair&>(a));
我知道编译器可能会在成员之后插入填充字节,但它也可以在第一个成员之前插入吗?
最佳答案
我认为这是定义的行为,假设 Pair
是标准布局。否则,它是未定义的行为。
首先,一个标准的布局类和它的第一个成员共享一个地址。 [basic.compound] 中的新措辞(澄清了之前的规则)如下:
Two objects a and b are pointer-interconvertible if:
* [...]
* one is a standard-layout class object and the other is the first non-static data member of that object, or, [...]
* [...]
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via areinterpret_cast
(5.2.10).
同样来自[class.mem]:
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class subobject (if any).
所以从 A
到 Pair
的 reinterpret_cast
没问题。如果 function
只访问 a
对象,那么该访问定义明确,因为 A
的偏移量为 0,所以行为是相当于让 function
直接接受 A&
。显然,对 b
的任何访问都是未定义的。
但是,虽然我相信代码是定义的行为,但这是个坏主意。它是 现在 定义的行为,但有一天可能有人会更改 function
以引用 pair.b
,然后你就会陷入痛苦的世界。简单地写会容易得多:
void function(A& a) { ... }
void function(Pair& p) { function(p.a); }
然后直接用你的a
调用函数
。
关于c++ - 结构对齐和类型重新解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39599219/