1

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.

3
  • The warning is correct for C++98, but not any later revisions. Maybe there is a setting to ignore C++98-only issues? Also the message is suspect. It doesn't include the () initializer which makes all the difference here. (That it makes all the difference seems very fragile btw. It could be made much safer without losing anything by just writing char *x{}; in the class definition.) Commented Jul 12, 2022 at 14:33
  • Don't use new when you don't have to. If you need a pointer to leverage (dynamic) polymorphism use std::make_unique. Otherwhise work with instances and references Commented Jul 12, 2022 at 15:38
  • Here is a nice article on the topic by Sy Brand with telling title Initialization in C++ is bonkers Commented Jul 12, 2022 at 18:34

1 Answer 1

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)

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.