[英]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;
如果 T 是没有用户提供或删除的默认构造函数的(可能是 cv 限定的)类类型,则该对象被零初始化并检查默认初始化的语义约束,并且如果 T 具有非平凡的默认构造函数, 对象是默认初始化的;
struct test
has a non-trivial constructor, this can be checked with: struct test
有一个非平凡的构造函数,可以通过以下方式检查:
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?标准是否暗示我的
test
对象在值初始化的情况下应始终为零初始化,然后默认初始化?
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
.我是否应该能够可靠地假设在执行
test *t = new test()
之后,如果我立即检查t->x == nullptr
,那应该是正确的,因为char *x
(指针/标量类型)应该为零-在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:我之所以问是因为 Coverity 给出了一个
Type: Uninitialized pointer read (UNINIT)
警告,因为如果您在值初始化后尝试执行类似if (t->x)
的操作,它会报告以下内容:
Assigning: "t" = "new test", which is allocated but not initialized.
赋值:"t" = "new test",已分配但未初始化。
Is Coverity misinterpreting the standard as "value-initialization if trivial constructor OR default-initialization if non-trivial constructor"? Coverity 是否将标准误解为“如果是平凡的构造函数则为值初始化,或者如果为非平凡的构造函数则为默认初始化”? If I remove the
std::string y;
如果我删除
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.成员,因此
test
有一个普通的默认构造函数,Coverity 不再有警告并假设char *x
成员是零初始化的。
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.对于它的价值,我只是使用
g++ -O3 -std=c++17
进行编译,并且我无法创建一个实际场景,其中我的test
对象不会发生零初始化。
The warning is not correct for modern C++(including C++17) as explained below.该警告不适用于现代 C++(包括 C++17),如下所述。
should I be able to reliably assume that after doing
test *t = new test();
我是否应该能够可靠地假设在完成
test *t = new test();
if I immediately checkt->x == nullptr
, that should be true becausechar *x
(a pointer / scalar type) should get zero-initialized during value-initialization of test.如果我立即检查
t->x == nullptr
,那应该是正确的,因为char *x
(指针/标量类型)应该在测试的值初始化期间进行零初始化。
Yes, it is guaranteed by the standard that x
is zero-initialized and hence the check t->x == nullptr
must evaluate to true
.是的,标准保证
x
是零初始化的,因此检查t->x == nullptr
必须评估为true
。 This can be seen from dcl.init#6 which states:这可以从dcl.init#6中看出:
To zero-initialize an object or reference of type T means:
对 T 类型的对象或引用进行零初始化意味着:
- 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 ;
如果 T 是(可能是 cv 限定的)非联合类类型,则其填充位初始化为零位,并且每个非静态数据成员、每个非虚拟基类子对象,并且如果对象不是基类子对象,每个虚拟基类子对象都是零初始化的;
(emphasis mine) (强调我的)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.