This is specifically regarding C++11:
#include <iostream>
struct A {
A(){}
int i;
};
struct B : public A {
int j;
};
int main() {
B b = {};
std::cout << b.i << b.j << std::endl;
}
Compiling with g++ 8.2.1:
$ g++ -std=c++11 -pedantic-errors -Wuninitialized -O2 a.cpp
a.cpp: In function ‘int main()’:
a.cpp:25:25: warning: ‘b.B::<anonymous>.A::i’ is used uninitialized in this function [-Wuninitialized]
std::cout << b.i << " " << b.j << std::endl
gcc is detecting b.i
as uninitialized, but I would think it should be getting zero-initialized along with b.j
.
From cppreference (C++11 specifically):
B
is not an aggregate because it has a base class. Public base classes were only allowed in aggregates in C++17.A
is not an aggregate because it has a user-provided constructorb
is getting list initialized with an empty braced-init-list- "If the braced-init-list is empty and T is a class type with a default constructor, value-initialization is performed."
B
has an implicitly-defined default constructor.
- Now during value-initialization: "if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized"
- So
b
gets zero-initialized
- So
- Now during zero-initialization: "If T is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored."
- So it's recursive.
b.B::A
gets zero-initialized, which zero-initalizesb.B::A.i
, and thenb.B::j
gets zero-initialized.
- So it's recursive.
However, it looks like gcc is saying only b.B::j
is going to get zero-initialized. Why is this? The only reason I can think of is if B
is being treated as an aggregate, which would initialize b.B::A
with an empty list. However B
should not be an aggregate in this case, correct?
Aucun commentaire:
Enregistrer un commentaire