问题描述
假设我有两种类型A和B.
Lets say I have two types A and B.
然后我创建这个类型
struct Pair{
A a;
B b;
};
现在我有一个这样的功能。
Now I have a function such as this.
void function(Pair& pair);
并假设 function
使用 a
部分。
然后是未定义的行为,以这种方式使用和调用函数?
Then is it undefined behavior to use and call the function in this way?
A a;
function(reinterpret_cast<Pair&>(a));
我知道编译器可以在成员之后插入填充字节,但是它也可以在第一个成员?
I know that a compiler may insert padding bytes after a member but can it also do it before the first member?
推荐答案
我认为它是定义的行为,假设 Pair
-布局。否则,它是未定义的行为。
I think it's defined behavior, assuming Pair
is standard-layout. Otherwise, it's undefined behavior.
首先,标准布局类及其第一个成员共享一个地址。在[basic.compound](澄清早期规则)中的新措辞如下:
First, a standard layout class and its first member share an address. The new wording in [basic.compound] (which clarifies earlier rules) reads:
也来自[class.mem]:
Also from [class.mem]:
reinterpret_cast
从 A
到配对
如果然后 function
只访问 a
对象,那么访问良好定义, $ c> A 是0,所以行为等同于 function
采取 A&
。显然,对 b
的任何访问都是未定义的。
So the reinterpret_cast
from A
to Pair
is fine. If then function
only ever access the a
object, then that access well-defined, as the offset of A
is 0, so the behavior is equivalent to having function
take an A&
directly. Any access to the b
would be undefined, obviously.
但,虽然我相信代码是定义的行为,这是一个坏主意。它定义的行为 NOW ,但有人有一天可能会改变 function
来引用 pair.b
然后你在一个痛苦的世界。这很容易写:
However, while I believe the code is defined behavior, it's a bad idea. It's defined behavior NOW, but somebody someday might change function
to refer to pair.b
and then you're in a world of pain. It'd be a lot easier to simply write:
void function(A& a) { ... }
void function(Pair& p) { function(p.a); }
并直接调用 function
a
。
这篇关于结构对齐和类型重新解释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!