C ++ 11成员类初始化的顺序

时间:2018-04-23 07:38:59

标签: c++ class c++11 initialization

我有代码:

struct testInit {
    testInit(int i1_) 
        : i1(i1_) {
        std::cout << "testInit::testInit" << std::endl;
    }

    int initI2() {
        std::cout << "testInit::initI2::i1: " << i1 << std::endl;
        return i1;
    }

    const int i1 = 1;
    const int i2 = initI2();

};

int main() {
    testInit ti(3);

    std::cout << "i1: " << ti.i1 << std::endl;
    std::cout << "i2: " << ti.i2 << std::endl;

    return 0;
}

输出为:

testInit::initI2::i1: 3
testInit::testInit
i1: 3
i2: 3

所以,我想知道什么是类成员的初始化顺序。我认为输出应该是i1:3和i2:1 - 这显然是错误的 - 但为什么呢?

3 个答案:

答案 0 :(得分:4)

  

我想知道什么是类成员初始化的顺序

成员始终initialized按照班级定义中的声明顺序排列,因此i1首先会被初始化,然后会i2

  

3)然后,按照类定义中的声明顺序初始化非静态数据成员。

对于testInit::testInit(int)i1上指定了成员初始值设定列表和default member initializer;将忽略默认成员初始值设定项。

  

如果成员具有默认成员初始值设定项并且也出现在构造函数的成员初始化列表中,则忽略默认成员初始值设定项。

然后,对于testInit ti(3);,首先使用i1通过成员初始值设定项列表初始化3,然后通过默认成员初始化程序使用i2初始化initI2(),然后它也是3

答案 1 :(得分:2)

来自dcl.init.list#4

  

在braced-init-list的初始化列表中,   初始化子条款,包括包扩展产生的任何条款,   按其出现的顺序进行评估。也就是说,每一个价值   与给定的初始化子句相关的计算和副作用   在每个值计算和副作用相关之前进行排序   与逗号分隔后面的任何initializer子句   初始化列表的列表。

适用于您的情况:

testInit ti(3); // replaces the default initialization of i1 using the mem-initializer 

然后i2默认初始化为3使用initI2() i1此时已3 testInit已经很好-defined)。

答案 2 :(得分:-1)

而不是引用标准 - 已经通过另一个答案完成 - 我给你一些经验数据:

#include <iostream>

struct testInit {
    testInit(int i1_) 
        : i1(i1_) {
        std::cout << "testInit::testInit" << std::endl;
    }

    int initI2() {
        std::cout << "testInit::initI2::i1: " << i1 << std::endl;
        return i1;
    }

    const int i2 = initI2();
    const int i1 = 1;
};

int main() {
    testInit ti(3);

    std::cout << "i1: " << ti.i1 << std::endl;
    std::cout << "i2: " << ti.i2 << std::endl;

    return 0;
}

输出:

testInit::initI2::i1: 0
testInit::testInit
i1: 3
i2: 0

这样的实验当然绝不足以确定C ++的某些行为,只是因为你很容易遇到未定义的行为(上面的代码实际上有)或者实现定义的行为。

尽管如此:只是试验一下。它不会受到伤害,你可能会更好地记住你所发现的东西与你在某处读到的东西。

由于访问未初始化的i1

未定义的行为