Reputation: 109
While refactoring a C-style struct to C++, I am facing a crash when creating a new object of the struct without {}.
I have illustrated the problem with the following code snippet.
struct A {
A() = default;
int* a1;
int* a2;
};
int main()
{
A a{};
std::cout << a.a1 << std::endl; //print 0000000000000000(nullptr)
A b;
std::cout << b.a1 << std::endl; //crash (0xcccccccccccccccc)
}
Why a.a1 is initialized to nullptr while b.a1 is not nullptr?
What is different between the two constructed objects?
I know a solution could be:
struct A {
A() = default;
int* a1 = nullptr;
int* a2 = nullptr;
};
Thanks,
Upvotes: 0
Views: 384
Reputation: 238461
Why a.a1 is initialized to nullptr
Because you value initialised a
. Empty braces are syntax for value initialisation.
while b.a1 is not nullptr?
Because you default initialised b
. Lack of any initialiser is syntax for default initialisation.
What is different between the two constructed objects?
One is value initialised and the other is default initialised.
I am facing a crash
The class is trivial(ly default constructible). When a trivial class is default initialised, its members are default initialised as well. A default initialised fundamental object such as a pointer has an indeterminate value. Such value is also commonly called "uninitialised".
Reading an indeterminate value results in undefined behaviour (there are rare exceptions which do not apply to this example). Crash is a possible outcome of undefined behaviour.
A decent compiler will warn you about the bug with a message such as this if you ask to be warned about bugs:
warning: 'b.A::a1' is used uninitialized in this function [-Wuninitialized]
Conclusions: Do not read uninitialised objects. Always initialise or at least assign all objects before first read. Use compiler warnings. Do not ignore compiler warnings. Avoid undefined behaviour.
Upvotes: 1
Reputation: 29985
If you use {}
, everything in the class is value-initialized. So, pointers become null-pointer, integers become 0, booleans become false, etc. If you don't, then the fields are default initialized with indeterminate values. Using these values in any way causes undefined behavior.
If you want everything to be deterministically initialized regardless, here is one way to do that:
struct A {
int* a1 = nullptr;
int* a2 = nullptr;
};
Here, anything you don't initialize explicitly is initialized for you. But the class is no longer trivially-constructible.
Read more about initialization in cppreference.
Upvotes: 5
Reputation: 610
It is known as uniform initialization it will initialize all the class variables with default values
A a{};
You created the object here but you have to manually initialize all the class variables
A b
Upvotes: 0