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

时间:2015-06-27 17:48:17

标签: c++ c++11 array-initialization member-initialization

考虑以下代码,我们根据D的另一部分初始化部分D

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

int main() {
    c C;
    assert(C.D[0] == C.D[1]);
}

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

4 个答案:

答案 0 :(得分:16)

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

struct S { int a; const char* b; int c; int d = b[a]; };
S ss = { 1, "asdf" };
     

使用ss.a初始化1ss.b "asdf"ss.c初始化int{}形式的表达式值(即,0)和ss.d,其值为ss.b[ss.a](即’s’

答案 1 :(得分: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.
};

但请考虑这个例子:

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).
};

此处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.
};

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

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.
};

答案 2 :(得分:2)

根据cppreference.com

  

聚合初始化的影响是:

     

每个数组元素或非静态类成员,按数组顺序排列   类定义中的下标/外观是从中复制初始化的   初始化列表的相应子句。

您的代码似乎很好。 然而,某种程度上令人困惑。

答案 3 :(得分:0)

  

写{{1}}不是一个好习惯,因为当时。{1}}   构造函数将运行它没有必要第一个rand()将是   然后执行D [0],这一切都取决于编译器,D [0]可以   首先执行,在这种情况下,d [1]将包含垃圾值。它   完全取决于编译器,它可以编译第二个参数   首先,然后是第一个参数,反之亦然,执行此操作   声明可能会导致未知行为。