为什么不将 C++ 结构初始化为 `= {0}` 将其所有成员设置为 0?
Why doesn't initializing a C++ struct to `= {0}` set all of its members to 0?
经过大量测试和编写 (注意:对它的反对票是 在 我完全重写它之前),我不明白为什么= {0}
没有将结构的所有成员设置为零!
如果你这样做:
struct data_t
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
};
data_t d3 = {0};
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
d3.num1, d3.num2, d3.num3, d3.num4);
...输出为:
d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150
...虽然我预期输出是这样的:
d3.num1 = 0
d3.num2 = 0
d3.num3 = 0
d3.num4 = 0
...这意味着只有第一个成员设置为零,其余所有成员都设置为默认值。
我一直以为以这三种方式中的任何一种方式初始化结构都会对其进行零初始化,但显然我错了!
data_t d{}
data_t d = {}
data_t d = {0}
因此,我从 中得出的关键结论是:
The big take-away here is that NONE of these: data_t d{}
, data_t d = {}
, and data_t d = {0}
, actually set all members of a struct to zero!
data_t d{}
sets all values to their defaults defined in the struct.
data_t d = {}
also sets all values to their defaults.
- And
data_t d = {0}
sets only the FIRST value to zero, and all other values to their defaults.
那么,为什么不将 C++ 结构初始化为 = {0}
将其所有成员设置为 0?
请注意,我上面的关键要点实际上与我多年来一直使用的这个看起来相当官方的文档相矛盾 (https://en.cppreference.com/w/cpp/language/zero_initialization),它说 T t = {} ;
和 T {} ;
都是零初始值设定项,而实际上,根据我的测试和上面的总结,它们不是。
参考文献:
- 更新:我也被指向了这个参考:What does {0} mean when initializing an object?
data_t d3 = {0}
是 list-initialization syntax which, with aggregates such as data_t
, performs aggregate initialization:提供的 0
值用于初始化第一个成员,其余成员使用相应的默认值进行初始化,如果 none存在,是 value-initialized(强调我的,针对 C++14 编辑):
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are initialized by their default member initializers, if provided in the class definition, and otherwise by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
value-initialization 表示非 class 类型的零初始化。 那就是为什么没有默认值的成员num3
得到值0
.
注意:不要与 default-initialization 混淆,后者根本不初始化非 class 类型。 data_t d3;
将是 默认初始化 ,成员 num3
将处于不确定状态。
需要注意的重点是被初始化的对象是否是一个聚合,因为聚合与class的初始化规则不同带有构造函数的es。对于构造函数,没有默认值的非 class 成员将被默认初始化(即处于不确定状态)。
一些例子:
struct A { // an aggregate
int num1 = 100;
int num2 = -100;
int num3;
};
struct B { // not an aggregate
int num1 = 100;
int num2 = -100;
int num3;
B() {}
B(int) {}
};
int main() {
A a1; // default-initialization: a1 is {100, -100, ???}
A a2 = {}; // aggregate initialization: a2 is {100, -100, 0}
A a3 = { 1 }; // aggregate initialization: a3 is {1, -100, 0}
A a4 = { 1,2,3 }; // aggregate initialization: a4 is {1, 2, 3}
B b1; // default-initialization: b1 is {100, -100, ???}
B b2 = {}; // copy-list-initialization invoking B::B(): b2 is {100, -100, ???}
B b3 = { 1 }; // copy-list-initialization invoking B::B(int): b3 is {100, -100, ???}
B b4 = { 1,2,3 }; // error: no B constructor taking (int,int,int)
}
另请注意,聚合初始化规则早于 C++11。例如,参见这个相关的 C++11 之前的问题:What does {0} mean when initializing an object?
So, why doesn't initializing a C++ struct to = {0} set all of its members to 0?
因为你只提供一个值,而class有多个成员。
当你有 T t{};
或 T t = {}
时,你所做的就是 value initialization。在值初始化中,如果 object/member 没有默认构造函数或默认成员初始化程序,则编译器回退到零初始化 objec/member。所以用
data_t d{}
成员的值按顺序为 100、-100、0、150 并且 0
为 num3
发生是因为它没有默认值并且您没有在{}
因此编译器回退到零初始化 num3
。这与data_t d = {}
相同。使用 data_t d = {0}
你提供第一个元素,所以 num1
是 0
,但是像前两个一样,所有其他成员都用它们的默认值初始化,如果它们有一个或零如果他们不这样做,则初始化,为成员值提供 0、-100、0、150。
这是在 C++11 发布并允许默认成员初始值设定项时发生的更改。
如果您的 data_t
定义为
typedef struct
{
int num1;
int num2;
int num3;
int num4;
} data_t;
然后 data_t d{}
、data_t d = {}
、data_t d = {0}
都会给你留下一个零初始化 class 因为没有默认的成员初始化器和你提供的唯一值您 braced-init-list({...}
的技术名称)为零,因此所有成员都变为零。
简短回答:因为你有 in-class 初始值设定项。
更长的答案:因为你正在为 C++14 或更高版本编译,所以有 in-class 初始化器并且你正在使用 aggregate initialization。参考提供解释:
If the number of initializer clauses is less than the number of
members or initializer list is completely
empty, the remaining members are initialized
by their default member initializers, if provided in the class
definition, and otherwise (since C++14) by empty lists, in accordance
with the usual list-initialization rules (which performs
value-initialization for non-class types and non-aggregate classes
with default constructors, and aggregate initialization for
aggregates).
要零初始化 all 数据成员,仅提供数据成员声明,不提供 in-class 初始化程序,然后使用 = {0}
或 ={}
语法:
struct data_t
{
int num1;
int num2;
int num3;
int num4;
};
int main()
{
data_t d3 = { 0 };
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
d3.num1, d3.num2, d3.num3, d3.num4);
}
现在,您的所有数据成员都已初始化为 0
。
经过大量测试和编写 = {0}
没有将结构的所有成员设置为零!
如果你这样做:
struct data_t
{
int num1 = 100;
int num2 = -100;
int num3;
int num4 = 150;
};
data_t d3 = {0};
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
d3.num1, d3.num2, d3.num3, d3.num4);
...输出为:
d3.num1 = 0
d3.num2 = -100
d3.num3 = 0
d3.num4 = 150
...虽然我预期输出是这样的:
d3.num1 = 0
d3.num2 = 0
d3.num3 = 0
d3.num4 = 0
...这意味着只有第一个成员设置为零,其余所有成员都设置为默认值。
我一直以为以这三种方式中的任何一种方式初始化结构都会对其进行零初始化,但显然我错了!
data_t d{}
data_t d = {}
data_t d = {0}
因此,我从
The big take-away here is that NONE of these:
data_t d{}
,data_t d = {}
, anddata_t d = {0}
, actually set all members of a struct to zero!
data_t d{}
sets all values to their defaults defined in the struct.data_t d = {}
also sets all values to their defaults.- And
data_t d = {0}
sets only the FIRST value to zero, and all other values to their defaults.
那么,为什么不将 C++ 结构初始化为 = {0}
将其所有成员设置为 0?
请注意,我上面的关键要点实际上与我多年来一直使用的这个看起来相当官方的文档相矛盾 (https://en.cppreference.com/w/cpp/language/zero_initialization),它说 T t = {} ;
和 T {} ;
都是零初始值设定项,而实际上,根据我的测试和上面的总结,它们不是。
参考文献:
- 更新:我也被指向了这个参考:What does {0} mean when initializing an object?
data_t d3 = {0}
是 list-initialization syntax which, with aggregates such as data_t
, performs aggregate initialization:提供的 0
值用于初始化第一个成员,其余成员使用相应的默认值进行初始化,如果 none存在,是 value-initialized(强调我的,针对 C++14 编辑):
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are initialized by their default member initializers, if provided in the class definition, and otherwise by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates). If a member of a reference type is one of these remaining members, the program is ill-formed.
value-initialization 表示非 class 类型的零初始化。 那就是为什么没有默认值的成员num3
得到值0
.
注意:不要与 default-initialization 混淆,后者根本不初始化非 class 类型。 data_t d3;
将是 默认初始化 ,成员 num3
将处于不确定状态。
需要注意的重点是被初始化的对象是否是一个聚合,因为聚合与class的初始化规则不同带有构造函数的es。对于构造函数,没有默认值的非 class 成员将被默认初始化(即处于不确定状态)。
一些例子:
struct A { // an aggregate
int num1 = 100;
int num2 = -100;
int num3;
};
struct B { // not an aggregate
int num1 = 100;
int num2 = -100;
int num3;
B() {}
B(int) {}
};
int main() {
A a1; // default-initialization: a1 is {100, -100, ???}
A a2 = {}; // aggregate initialization: a2 is {100, -100, 0}
A a3 = { 1 }; // aggregate initialization: a3 is {1, -100, 0}
A a4 = { 1,2,3 }; // aggregate initialization: a4 is {1, 2, 3}
B b1; // default-initialization: b1 is {100, -100, ???}
B b2 = {}; // copy-list-initialization invoking B::B(): b2 is {100, -100, ???}
B b3 = { 1 }; // copy-list-initialization invoking B::B(int): b3 is {100, -100, ???}
B b4 = { 1,2,3 }; // error: no B constructor taking (int,int,int)
}
另请注意,聚合初始化规则早于 C++11。例如,参见这个相关的 C++11 之前的问题:What does {0} mean when initializing an object?
So, why doesn't initializing a C++ struct to = {0} set all of its members to 0?
因为你只提供一个值,而class有多个成员。
当你有 T t{};
或 T t = {}
时,你所做的就是 value initialization。在值初始化中,如果 object/member 没有默认构造函数或默认成员初始化程序,则编译器回退到零初始化 objec/member。所以用
data_t d{}
成员的值按顺序为 100、-100、0、150 并且 0
为 num3
发生是因为它没有默认值并且您没有在{}
因此编译器回退到零初始化 num3
。这与data_t d = {}
相同。使用 data_t d = {0}
你提供第一个元素,所以 num1
是 0
,但是像前两个一样,所有其他成员都用它们的默认值初始化,如果它们有一个或零如果他们不这样做,则初始化,为成员值提供 0、-100、0、150。
这是在 C++11 发布并允许默认成员初始值设定项时发生的更改。
如果您的 data_t
定义为
typedef struct
{
int num1;
int num2;
int num3;
int num4;
} data_t;
然后 data_t d{}
、data_t d = {}
、data_t d = {0}
都会给你留下一个零初始化 class 因为没有默认的成员初始化器和你提供的唯一值您 braced-init-list({...}
的技术名称)为零,因此所有成员都变为零。
简短回答:因为你有 in-class 初始值设定项。
更长的答案:因为你正在为 C++14 或更高版本编译,所以有 in-class 初始化器并且你正在使用 aggregate initialization。参考提供解释:
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are initialized by their default member initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, in accordance with the usual list-initialization rules (which performs value-initialization for non-class types and non-aggregate classes with default constructors, and aggregate initialization for aggregates).
要零初始化 all 数据成员,仅提供数据成员声明,不提供 in-class 初始化程序,然后使用 = {0}
或 ={}
语法:
struct data_t
{
int num1;
int num2;
int num3;
int num4;
};
int main()
{
data_t d3 = { 0 };
printf("d3.num1 = %i\nd3.num2 = %i\nd3.num3 = %i\nd3.num4 = %i\n\n",
d3.num1, d3.num2, d3.num3, d3.num4);
}
现在,您的所有数据成员都已初始化为 0
。