总结笔记-c++成员变量、构造函数以及析构函数的执行顺序

来源:互联网 发布:淘宝申请介入流程 编辑:程序博客网 时间:2024/06/06 02:44

在我的之前的博客http://blog.csdn.net/caoyan_12727/article/details/52356844有提到c++各种变量的初始化规则,本文将总结c++中涉及到的各种变量的初始化顺序和析构函

以及构造函数初始化的顺序!!

第一步:类的静态成员变量

#include <stdlib.h>#include <sys/types.h>#include <assert.h>#include <iostream>#include<memory>using namespace std;class a{public:int a1;int a2;static int a3;a(int x) :a1(x){a2 = 2;a3 = 7;}};//int a::a3 = 4;int main(){a aa(2);cout << a::a3 << endl;return 0;}
我们把int a::a3这一行注释掉,vs2103编译器提示错误:


直接显示未定义的外部变量,说明在类中的static int a3语句连定义都算不上,一定要在类外进行定义!!!

第二步:全局变量和类中静态变量的执行顺序:

测试程序:

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <assert.h>#include <iostream>#include<memory>#include <iostream>#include <string>using namespace std;struct B{B(){ std::cout << "b\n"; }};struct C{C(){ std::cout << "c\n"; }};struct D{D(){ std::cout << "d\n"; }};struct E{E(){ std::cout << "e\n"; }};struct F{F(){ std::cout << "f\n"; }};struct A{static B b;D d;C c;A() :d(), c(){}};struct AA :A{static E e;};F f;B A::b;E AA::e;int main(){A a;return 0;}
测试结果:

替换顺序:

B A::b;F f;E AA::e;

测试结果:


可以看到,在全局变量、父类静态变量子类静态变量同时存在的情况下,初始化规则是按照它们定义的先后顺序进行的,同时在类中,比如在类A中,成员c和成员d的初始化顺序和它们的定义顺序是一样的,即先初始化成员d,然后初始化成员c!!!因为类的静态成员同样被存储在.data段,它们可以看做是带有“特殊作用域的全局变量”。

第三步:基类和虚基类的析构函数和构造函数的调用顺序

测试代码:

#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <assert.h>#include <iostream>#include<memory>using namespace std;class a{public:int a1;int a2;a(int x) :a1(x){cout << "construct class a!" << endl;}~a(){cout << "discontruct class a!" << endl;}};class b{public:int b1;int b2;b(int x) :b1(x){cout << "construct class b!" << endl;}~b(){cout << "discontruct class b!" << endl;}};class d{public:int d1;int d2;d(){cout << "construct class d!" << endl;}~d(){cout << "distconruct class d!" << endl;}};class e{public:int e1;int e2;e(){cout << "construct class e!" << endl;}~e(){cout << "discontruct class e!" << endl;}};class c :virtual public d, public  b, public a, virtual public e{public:int c1;int c2;c(int x, int y, int z) :a(y), b(z), c1(x){cout << "construct clsss c! " << endl;}~c(){cout << "discontruct class c!" << endl;}};int con(){c two(1, 2, 3);return 0;}int main(){con();return 0;}
测试输出:



修改继承顺序:

class c :virtual public e, public  a, public b, virtual public d{public:int c1;int c2;c(int x, int y, int z) :a(y), b(z), c1(x){cout << "construct clsss c! " << endl;}~c(){cout << "discontruct class c!" << endl;}};
输出结果:



在例子中类c虚拟继承类d和类e,普通继承类a和类吧,从构造函数可以看出,在同一层次的继承中,虚拟继承的构造函数要先于非虚拟继承的构造函数,在同一层的所有非虚拟继承的类中,其构造函数的执行顺序是先左后右,同样的在同一层所有非虚拟继承的类中,构造函数的执行也是先左后右,和类的定义顺序无关!!无关!!

struct B{public:int b1;int b2;B(int x,int y):b1(x),b2(y){cout << "b" << endl;}};struct D{public:D(){cout << "d" << endl;}};struct C{public:D d;B b;<strong><span style="color:#ff0000;">C():b(1,2){ std::cout << "c\n"; }</span></strong>};int main(){C c;return 0;}
输出结果:


第四步:函数中的局部静态变量初始化

struct B{int b1 = 1;B(){ std::cout << "b\n"; }};struct C{int c1 = 2;C(){ std::cout << "c\n"; }};struct D{int d1 = 3;D(){ std::cout << "d\n"; }};struct E{int e1 = 4;E(){ std::cout << "e\n"; }};struct F{int f1 = 5;F(){ std::cout << "f\n"; }};void func(){static D d;}B b;C c;static F f;int main(){E e;func();return 0;}
测试结果:



所以总结一下c++的变量初始化顺序:

(1)先初始化全局变量和全局静态变量(不管是不是类里面的静态变量,因为此时类中的静态变量会被当做全局变量看待),如果有局部静态变量,则在局部函数被调用时,它里面的局部静态变量才会初始化;不管是基类中的静态变量还是派生类中的静态变量,它们都存储在.data段,会被当做全局变量来看待,所以它的初始化和它们的定义顺序一致!!!

(2)在成员初始化列表中,成员初始化的顺序和定义的顺序一致,和在初始化列表里出现的顺序无关;

0 0