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_x
在B
类中被声明为之前 m_a
,B(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::A
和B::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
时,首先构造B
的A
部分。这会在输出中给出0
。然后我们得到2
,因为m_x(++m_i)
首先发生,因为m_x
在类中列在第一位。由于m_i
是B
的A
部分中的1,正在构造++m_i
给出2
,现在我们有02
。然后运行m_a(new A[2])
,这给了我们2 个0
(每个数组成员一个)。这使我们位于0200
。然后我们从 std::cout << m_i;
得到最终的2
,因为m_i
仍然是来自m_x(++m_i)
的2
。
【讨论】:
以上是关于C++ - 成员初始化和递增的顺序的主要内容,如果未能解决你的问题,请参考以下文章