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.