在其自身的初始化方法中访问结构体的成员未定义的行为 [英] Is accessing a member of a struct in its own initializer undefined behaviour
问题描述
请考虑:
struct A {void do_something(){}};
struct B {
A&一个;
B(A& a):a {a} {a.do_something(); }
};
struct C {
A a; B b;
C(A& a):b {a} {}
};
int main(){
C c {c.a};
}
似乎有可能工作,因为:
- 甚至在初始化
c
之前,我们知道它的内存布局和ca
- 的地址,我们实际上不会使用
ca
,直到它被初始化。
此外,我没有在几个不同的编译器下收到警告。 / p>
但是,我经历了一些非常奇怪的行为(稍后),只能做一些未定义的事情,而且只有当我重组我的程序,以避免这种模式。
谢谢。
回答,
您的代码是一个狡猾的...因为,尽管在初始化之前使用一个对象,你的代码的行为是显而易见的。
如何?
在 c
的构造中,会发生以下事件序列:
-
您呼叫
C
的建构函式,C(A& a):b {a} {}
它引用A
类型的对象。 (引用就像一个地址,正如你所说的,c.a
的地址在编译时是已知的)。你的调用是:C c {ca};
和编译器很好,因为ca
/ p> -
由于
C
的会员声明顺序...struct C {
A a; B b;
C(A& a):b {a} {}
};
对象
a
c $ c> b 。 -
因此,
a
其在成员初始化程序中的使用...b {a}
但是,您可以通过 optimizers ...
Consider:
struct A { void do_something() {} };
struct B {
A& a;
B(A& a) : a{a} { a.do_something(); }
};
struct C {
A a; B b;
C(A& a) : b{a} {}
};
int main() {
C c{ c.a };
}
It seems possible that this could be made to work, because:
- even before
c
is initialized, we know its memory layout and the address ofc.a
- we don't actually use
c.a
until it is initialized.
Additionally, I didn't get a warning under a few different compilers.
However, I experienced some extremely odd behaviour (a bit later on) that could only be down to doing something undefined, and which only went away when I reorganised my program to avoid this pattern.
Thanks.
In addition to my previous answer,
Your code is a crafty one... Because, despite the supposed UB with using an object before its initialized, the behaviour of your code is apparently well defined..
How?
In the construction of c
, the following sequence of events will happen:
You call
C
's constructor,C(A& a) : b{a} {}
which takes a reference to an object of typeA
. (A reference is just like an address, and as you rightly mentioned, the address ofc.a
is known at compile time). Your call is:C c{ c.a };
and the compiler is fine with that sincec.a
is an accessible nameDue to the order of declaration of
C
's members...struct C { A a; B b; C(A& a) : b{a} {} };
the object
a
is initialized beforeb
.Thus,
a
becomes alive before its use in the member initializer...b{a}
But again, you can be smoked by optimizers...
这篇关于在其自身的初始化方法中访问结构体的成员未定义的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!