George
George

Reputation: 35

Are struct scalar members zero-initialized when using value-initialization on a struct with a default non-trivial-constructor

If I have the following struct

struct test
{
    char *x;
    std::string y;
};

And I initialize with

test *t = new test();

That should value-initialize the object and do the following based on the standard:

if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

struct test has a non-trivial constructor, this can be checked with:

static_assert(std::is_trivially_constructible<test>::value, "test is not is_trivially_constructible");`)

Does the standard imply that my test object should always be zero-initialized in the case of value-initialization, and then subsequently default-initialized?

And should I be able to reliably assume that after doing test *t = new test() if I immediately check t->x == nullptr, that should be true because char *x (a pointer / scalar type) should get zero-initialized during value-initialization of test.

I ask because Coverity gives a Type: Uninitialized pointer read (UNINIT) warning because it reports the following if you try do something like if (t->x) after value-intialization:

Assigning: "t" = "new test", which is allocated but not initialized.

Is Coverity misinterpreting the standard as "value-initialization if trivial constructor OR default-initialization if non-trivial constructor"? If I remove the std::string y; member so that test has a trivial-default-constructor, Coverity no longer has a warning and assumes the char *x member is zero-initialized.

For what it's worth, I'm just using g++ -O3 -std=c++17 to compile and I have not been able to create an actual scenario where zero-intialization doesn't happen for my test object.

Upvotes: 1

Views: 537

Answers (1)

user12002570
user12002570

Reputation: 1

The warning is not correct for modern C++(including C++17) as explained below.

should I be able to reliably assume that after doing test *t = new test(); if I immediately check t->x == nullptr, that should be true because char *x (a pointer / scalar type) should get zero-initialized during value-initialization of test.

Yes, it is guaranteed by the standard that x is zero-initialized and hence the check t->x == nullptr must evaluate to true. This can be seen from dcl.init#6 which states:

To zero-initialize an object or reference of type T means:

  • if T is a (possibly cv-qualified) non-union class type, its padding bits are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized;

(emphasis mine)

Upvotes: 1

Related Questions