Reputation: 477650
From a comment on this answer:
Class members are initialized in their order of declaration. By this logic, the following constructor should invoke undefined behaviour:
struct Foo
{
Bar a;
Bar b;
Foo(Bar c) : a(b = c) { }
};
Patently, we are assigning to b
first before a
has been initialized. Assigning to an uninitialized object should be UB. It's not surprising that the code "works" with Bar = int
, but if I make Bar
a heavy class with constructors, I see that b
does indeed get initialized before a
.
(For extra lunacy, we can even say Foo(Bar c, Bar d) : a(b = c), b(d) { }
, still with no warning.)
Yet GCC 4.6.1 doesn't warn about this. Is this acceptable, well-defined behaviour, or is this strictly wrong?
Upvotes: 4
Views: 263
Reputation: 47498
Given a Bar
where non-initialized state actually matters to the assignment operator, I get warnings from 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: https://ideone.com/VDZzG
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
Other compilers I've tried don't seem to care, though...
Upvotes: 4