在我的之前的博客http://blog.csdn.net/caoyan_12727/article/details/52356844有提到c++各种变量的初始化规则,本文将总结c++中涉及到的各种变量的初始化顺序和析构函
以及构造函数初始化的顺序!!
第一步:类的静态成员变量
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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;
C():b(1,2){ std::cout << "c\n"; }
};
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)在成员初始化列表中,成员初始化的顺序和定义的顺序一致,和在初始化列表里出现的顺序无关;