C++ - 成员初始化和递增的顺序

Posted

技术标签:

【中文标题】C++ - 成员初始化和递增的顺序【英文标题】:C++ - order of member initialization and incrementation 【发布时间】:2015-12-23 16:15:17 【问题描述】:

我正在寻找一些测试来提高我的 C++ 知识。这是其中的一个练习:以下程序的输出是什么?

#include <iostream>

class A

public:
    A(int n = 0) : m_i(n)
    
        std::cout << m_i;
        ++m_i;
    

protected:
    int m_i;
;

class B : public A

public:
    B(int n = 5) : m_a(new A[2]), m_x(++m_i)  std::cout << m_i; 

    ~B()  delete [] m_a; 

private:
    A m_x;
    A *m_a;
;

int main()

    B b;
    std::cout << std::endl;
    return 0;

嗯,我试过这段代码,答案是02002。我来这里是为了解释一下,因为我不明白为什么02002 是结果。 我会解释我的推理,但请有人告诉我我哪里错了?

让我们调用“str”来打印当前字符串。构建b 对象时:

    A 的构造函数被调用。 str => 0, m_i => 1 m_a(new A[2]) 的构造。 str => 000 m_x(++m_i) 的构造。 str => 0002, m_i => 3 str 的最后更新(在B 的构造函数中)=> str => 00023

这是我的问题:

为什么最终值是m_i 2 而不是3? 为什么m_x(++m_i)的构造在m_a(new A[2])之前完成?我尝试交换 m_x 和 m_a 的初始化位置,结果还是一样:02002

【问题讨论】:

由于m_xB 类中被声明为之前 m_aB(int n = 5) : m_a(new A[2]), m_x(++m_i) 格式错误,应该是B(int n = 5) : m_x(++m_i), m_a(new A[2]) @YSC 是正确的,至少,使用 gcc 编译时会收到大量警告(我不确定其他人) @YSC B(int n = 5) : m_a(new A[2]), m_x(++m_i) 不是格式错误的。也许它应该是不合格式的,但不幸的是它不是。 你是对的,我收到警告:“test.cpp:27: warning: ‘B::m_a’ will be initialized after” 【参考方案1】:

为什么m_i的最终值是2而不是3

因为new A[2] 创建了两个与*this 无关的独立实例。 b 实例的m_i 仅在A::AB::B 中递增(两次)。

如果m_i的增量应该在同一个实例上执行(例如m_i是一个引用),那么认为m_i的最终值应该是@987654334会更合理@(数组中有两个对象 - 两个额外的增量)。

为什么m_x(++m_i)的构造在m_a(new A[2])之前完成?

因为the order of initialization depends on the order of declaration of the data members,而不是您在成员初始化器列表中编写初始化的顺序。

【讨论】:

感谢您的回答!我刚刚明白为什么是 2 而不是 3。我还在 m_x 的构造过程中添加了一个增量。 @Ptiseb 如果您以与声明成员不同的顺序初始化成员,一些编译器(MingW 和 VC)会发出警告。【参考方案2】:

当您构造b 时,首先构造BA 部分。这会在输出中给出0。然后我们得到2,因为m_x(++m_i)首先发生,因为m_x在类中列在第一位。由于m_iBA 部分中的1,正在构造++m_i 给出2,现在我们有02。然后运行m_a(new A[2]),这给了我们2 个0(每个数组成员一个)。这使我们位于0200。然后我们从 std::cout &lt;&lt; m_i; 得到最终的2,因为m_i 仍然是来自m_x(++m_i)2

【讨论】:

以上是关于C++ - 成员初始化和递增的顺序的主要内容,如果未能解决你的问题,请参考以下文章

C++成员初始化列表

c++ 类成员的初始化顺序

c++类成员变量初始化详解

派生类(构造函数)中基类的成员变量初始化顺序

C++类和对象下

第20课.初始化列表