阵列成员可以自我引用初始化吗?

eml*_*lai 22 c++ array-initialization member-initialization c++11

考虑以下代码,我们在其中D基于另一部分初始化部分D:

struct c {
    c() : D{rand(), D[0]} {}
    int D[2];
};

int main() {
    c C;
    assert(C.D[0] == C.D[1]);
}
Run Code Online (Sandbox Code Playgroud)

以上程序定义明确吗?我们可以安全地使用同一阵列的一部分来初始化它的另一部分吗?

Ker*_* SB 16

当聚合(包括数组)从支撑列表初始化时,每个聚合元素都从列表的相应元素初始化("以增加的下标或成员顺序").即使我找不到一个确切的规则,即每个元素的初始化都在前一个元素之后进行排序,但标准中的一个例子清楚地表明这是预期的含义.该示例位于[dcl.init.aggr]中:

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };
Run Code Online (Sandbox Code Playgroud)

初始化ss.a1,ss.b"asdf",ss.c与所述形式的表达的值int{}(即,0),和ss.d用的值ss.b[ss.a](即,’s’)

  • [dcl.init.list]/4:"在braced-init-list的initializer-list中,initializer-clause,包括pack扩展(14.5.3)产生的任何结果,按照它们的顺序进行评估.也就是说,与给定初始化子句相关联的每个值计算和副作用在每个值计算和与初始化列表的逗号分隔列表中跟随它之后的任何初始化子句相关联的副作用之前被排序. (3认同)
  • @Casey:副作用是否包括聚合成员的初始化? (2认同)

And*_* DM 11

阵列成员可以自我引用初始化吗?

是.

struct c {
    int a[3];
    c() : a{4, a[0], 3} {} // a[0] is initialized to 4.
                           // a[1] is initialized to whatever a[0] is. (4)
                           // a[2] is initialized to 3.
};
Run Code Online (Sandbox Code Playgroud)

但请考虑这个例子:

struct c {
    int a[3];
    c() : a{a[1], 4, a[1]} {} // a[0] is initialized to whatever a[1] is.(Garbage value)
                              // a[1] is initialized to 4.
                              // a[2] is initialized to what a[1] is now (4).
};
Run Code Online (Sandbox Code Playgroud)

这里的第一个元素a将是任何值a[1],其中很可能是垃圾值.第二个元素初始化为4,第三个元素初始化为现在a[1]的值,即值4.

此外,如果未列出数组中的所有{}元素,则未列出的元素将默认初始化:

struct c {
    int a[5]; // notice the size
    c() : a{a[1], 2, 3, 4}{}  // a[0] will get value that is in a[1]
                              // but since a[1] has garbage value,
                              // it will be default initialized to 0.
                              // a[1] = 2
                              // a[2] = 3
                              // a[3] = 4
                              // a[4] is not listed and will get 0.
};
Run Code Online (Sandbox Code Playgroud)

但是,列出已初始化的元素将为您提供所需的值.
使用以上示例:

struct c {
    int a[5];
    c() : a{1, a[0], 3, 4}{}  // a[0] = 1
                              // a[1] = 1
                              // a[2] = 3
                              // a[3] = 4
                              // a[4] is not listed and will get 0.
};
Run Code Online (Sandbox Code Playgroud)