来自对this answer的评论:
类成员按其声明顺序初始化。通过这种逻辑,以下构造函数应该调用未定义的行为:
struct Foo
{
Bar a;
Bar b;
Foo(Bar c) : a(b = c) { }
};
很明显,我们在b
初始化之前首先分配给a
。分配给未初始化的对象应该是UB。代码与Bar = int
“一致”并不奇怪,但如果我使Bar
成为构造函数的重类,我会发现b
确实在a
之前初始化了。
(对于额外的精神错乱,我们甚至可以说Foo(Bar c, Bar d) : a(b = c), b(d) { }
,仍然没有任何警告。)
然而GCC 4.6.1并没有对此发出警告。这是可接受的,定义明确的行为,还是严格错误?
答案 0 :(得分:4)
给定Bar
非初始化状态对赋值运算符实际上很重要,我收到GCC的警告:
#include <iostream>
struct Bar {
int n;
Bar(int v) : n(v) {
std::cout << "Bar " << n << " constructed\n";
}
Bar& operator=(const Bar& other) {
std::cout << "Bar " << n << " assigned from " << other.n << "\n";
n = other.n;
return *this;
}
};
struct Foo
{
Bar a;
Bar b;
Foo(Bar c, Bar d) : a(b = c), b(d) { }
};
int main()
{
Foo f(Bar(1), Bar(2));
}
test.cc: In function ‘int main()’:
test.cc:8:32: warning: ‘*((void*)(& f)+4).Bar::n’ is used uninitialized in this function [-Wuninitialized]
test.cc:23:13: note: ‘*((void*)(& f)+4).Bar::n’ was declared here
我试过的其他编译器似乎并不关心,但是......