结构体中的 {0, 0} 是否会初始化数组?

10

在这段代码中,C.B 的所有100个项都会被初始化为零吗?

struct A { int B[100]; int D; };
A C = {0, 0};
似乎它起作用了,但是可能事先内存是空的。

这不是重复的,你能看出初始化数组和结构体之间的区别吗? - exebook
A C = {0}; 执行聚合类型的值初始化,因此它会对每个成员执行值初始化。因此,数组成员确实被清零了。 - vsoftco
@vsoftco,应该是{{0}}吗? - exebook
有一些规则(我记不清楚了)说你可以省略聚合体的大括号。在这里:http://en.cppreference.com/w/cpp/language/aggregate_initialization "如果聚合初始化使用等号形式(T a = {args..}),(直到C++14),嵌套初始化列表周围的大括号可以省略(省略)..." - vsoftco
1
顺便提一下,这里有一个答案:https://dev59.com/MWgu5IYBdhLWcg3wso6i 但我仍然认为这个问题应该再次开放。 - Denilson Amorim
显示剩余5条评论
1个回答

5

这条线

A C = {0, 0}; 

执行 值初始化 聚合 A。根据标准,可以省略大括号进行聚合初始化:

8.5.1 聚合体[dcl.init.aggr]/12

Braces can be elided in an initializer-list as follows. If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate; it is erroneous for there to be more initializer-clauses than members. If, however, the initializer-list for a sub- aggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.

[Example:

 float y[4][3] = {
   { 1, 3, 5 },
   { 2, 4, 6 },
   { 3, 5, 7 }, }; 

is a completely-braced initialization: 1, 3, and 5 initialize the first row of the array y[0], namely y[0][0], y[0][1], and y[0][2]. Likewise the next two lines initialize y[1] and y[2]. The initializer ends early and therefore y[3]'s elements are initialized as if explicitly initialized with an expression of the form float(), that is, are initialized with 0.0. In the following example, braces in the initializer-list are elided; however the initializer-list has the same effect as the completely-braced initializer-list of the above example,

 float y[4][3] = {
   1, 3, 5, 2, 4, 6, 3, 5, 7 }; 

The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used. Likewise the next three are taken successively for y[1] and y[2]. — end example ]

下一步

8.5.1 聚合体[dcl.init.aggr]/7

如果初始化器列表中的初始化子句比聚合体中的成员少,则未明确初始化的每个成员都应从其大括号或等号初始化程序进行初始化,如果没有大括号或等号初始化程序,则应从空初始化程序列表进行初始化。

在您的情况下,这意味着第一个0被分配给B [0],第二个0被分配给B [1]。然后根据 8.5.1/7 ,其余元素将进行值初始化。

但是,在这种情况下,为了清晰起见,您应该使用A C = {{0},0};或更好的方法

A C{}; // or A C = {};

唯一让我有点担心的是 g++ 的警告 (-Wextra):

warning: missing initializer for member 'main()::A::D' [-Wmissing-field-initializers] A C {0,0};

但根据我对上面标准的解释,你应该没问题,D 应该已经被初始化了。我甚至使用了一些放置 new,结果也和预期一样。

#include <iostream>

int main()
{
    struct A { int B[100]; int D;};
    A memory{};
    memory.D = 42; 
    std::cout << memory.D << std::endl;

    // let's place something an A at the location of memory
    A* foo = new (&memory) A{0,0}; 
    // line below outputs 0, so D is erased; not the case if A* foo = new (&memory) A; 
    std::cout << memory.D << std::endl; // outputs 0
}

1
我已经编辑了问题,所以它不再是 {0},而是 {0,0}。这样可以更清楚地表达我的实际考虑。 - exebook

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接