C++实例化含A类成员的B对象输出abBA的原因是什么
C++对象构造析构顺序问题解答
首先给出问题复现代码:
#include <iostream> class A { public: A() { std::cout << 'a'; } ~A() { std::cout << 'A'; } }; class B { public: B() { std::cout << 'b'; } ~B() { std::cout << 'B'; } A a; }; int main() {B b; }
为什么输出结果是abBA
输出完全对应对象构造、析构两个阶段的固定执行逻辑:
- 构造阶段:main函数中创建局部对象
b时,首先构造B类的成员对象a,调用A的构造函数输出字符a;成员构造完成后才进入B的构造函数体,输出字符b,构造阶段完成后输出前缀为ab。 - 析构阶段:main函数执行结束时局部对象
b生命周期终止,析构顺序和构造顺序完全相反。首先执行B自身的析构函数体,输出字符B;B的析构逻辑执行完后,才会销毁其成员对象a,调用A的析构函数输出字符A,最终完整输出为abBA。
为什么成员对象的构造早于类自身构造函数逻辑执行
这是C++标准强制规定的初始化规则,核心目的是保证初始化安全:类构造函数体里的逻辑是可以合法访问自身所有成员、调用基类接口的,如果在执行构造函数体时,成员或者基类还没有完成构造,一旦代码访问了这些未初始化的子对象,就会触发未定义行为。因此标准要求,在进入当前类构造函数体之前,所有基类子对象、成员子对象必须完成初始化。
C++构造、析构流程的固定执行顺序
C++对对象的构造、析构顺序有明确的强制规定,不受初始化列表书写顺序影响,优先级从高到低如下:
构造顺序(先执行的排在前面)
- 虚基类子对象:多继承场景下存在虚基类时,最先构造虚基类,多个虚基类按继承声明的从左到右顺序构造
- 直接基类子对象:按类继承声明时的从左到右顺序构造
- 非静态成员对象:按成员在类中声明的从上到下顺序构造
- 当前类构造函数体:所有子对象构造完成后,最后执行构造函数内的自定义逻辑
注意:构造函数的初始化列表只能控制对应子对象的初始化参数,无法改变上述构造顺序。
析构顺序(先执行的排在前面)
析构顺序是构造顺序的严格逆序,没有例外:
- 当前类析构函数体:对象销毁时最先执行自身析构函数内的自定义逻辑
- 非静态成员对象:按成员声明顺序的逆序销毁,后声明的成员先析构
- 直接基类子对象:按继承声明顺序的逆序销毁,后继承的基类先析构
- 虚基类子对象:按虚基类声明顺序的逆序销毁,最后完成虚基类的析构
内容的提问来源于stack exchange,提问作者mahmod AL-Athamnneh
相关产品推荐
相关产品推荐

