全局变量,局部静态变量初始化以及类静态成员变量初始化

全局变量、文件域的静态变量和类的静态成员变量在main执行之前的静态初始化过程中分配内存并初始化;局部静态变量(一般为函数内的静态变量)在第一次使用时分配内存并初始化。这里的变量包含内置数据类型和自定义类型的对象。

class B{
public:
	B()
	{
		cout << "B constructor called" << endl;
	}
	~B()
	{
		cout << "B desconstructor called" << endl;
	}
};
class A{
public:
	A()
	{
		cout << "A constructor called" << endl;
	}
	~A()
	{
		cout << "A desconstructor called" << endl;
	}
private:
	static B b;
};

class C{
public:
	C()
	{
		cout << "C constructor called" << endl;
	}
	~C()
	{
		cout << "C desconstructor called" << endl;
	}
};
class D{
public:
	D()
	{
		cout << "D constructor called" << endl;
	}
	~D()
	{
		cout << "D desconstructor called" << endl;
	}
};
class E{
public:
	E()
	{
		cout << "E constructor called" << endl;
	}
	~E()
	{
		cout << "E desconstructor called" << endl;
	}
};
int f()
{
	system("pause");
	return 0;
}
C c;
static E e;
B A::b = B();//静态成员变量在类外初始化
int main()
{
	_onexit(f);
	A *pa = new A;
	B b;
	static D d;
	delete pa;
	return 0;
}
输出:

C constructor called//全局变量初始化在main执行之前
E constructor called//全局静态变量初始化在main之前

B constructor called//类中的静态成员变量在类外初始化在main之前

A constructor called//main中执行A的默认构造函数,但是没有调用B的默认构造函数,(若A中的成员变量b不是static型的,那么在调用A的构造函数                                                                                                             时,系统会调用B的默认构造函数,这里涉及到构造函数成员初始化列表的作用)

B constructor called//构造b

D constructor called//局部静态变量在第一次使用时初始化

A desconstructor called//显示调用A的析构

B desconstructor called//局部变量在栈上,早析构

D desconstructor called//局部静态变量出了main后析构

B desconstructor called//类的静态成员变量析构

E desconstructor called//全局静态变量析构

C desconstructor called//全局变量析构,这后边三个析构顺序,应该和它们的构造顺序相反!!!!

下边内容转载:

有些成员变量的数据类型比较特别,它们的初始化方式也和普通数据类型的成员变量有所不同。这些特殊的类型的成员变量包括:

a.引用

b.常量

c.静态

d.静态常量(整型)

e.静态常量(非整型)

常量和引用,必须通过参数列表进行初始化。这里不包括常量静态成员变量,因为无法通过构造函数初始化静态类数据。但是非常量静态类数据,可以通过构造函数体赋值。

例如:

class Test {
public:
	int a;
	static int b;
public:
	Test(int _a, int _b) : a(_a){
		b = _b;
	}
};
int Test::b;
int main() {
	Test t1(0, 0), t2(1, 1);
	t1.b = 10;
	t2.b = 20;
	printf("%u %u %u %u", t1.a, t1.b, t2.a, t2.b);
	system("pause");
	return 0;
}
但如果是常量静态类数据就不行了,因为不能对常量赋值。

静态成员变量的初始化也颇有点特别,是在类外初始化且不能再带有static关键字,记住是类外初始化,但可以在构造函数中赋值 ,其本质见文末。

参考下面的代码以及其中注释:

    #include   
    using namespace std;  
      
    class BClass  
    {  
    public:  
     BClass() : i(1), ci(2), ri(i){} // 对于常量型成员变量和引用型成员变量,必须通过参数化列表的方式进行初始化  
                                                    //普通成员变量也可以放在函数体里,但是本质其实已不是初始化,而是一种普通的运算操作-->赋值运算,效率也低  
    private:  
     int i;                                  // 普通成员变量  
     const int ci;                           // 常量成员变量  
     int &ri;                                // 引用成员变量  
     static int si;                          // 静态成员变量  
     //static int si2 = 100;                 // error: 只有静态常量成员变量,才可以这样初始化  
     static const int csi;                   // 静态常量成员变量  
     static const int csi2 = 100;            // 静态常量成员变量的初始化(Integral type)    (1)  
     static const double csd;                // 静态常量成员变量(non-Integral type)  
     //static const double csd2 = 99.9;      // error: 只有静态常量整型数据成员才可以在类中初始化  
    };  
      
    //注意下面三行:不能再带有static  
    int BClass::si = 0; // 静态成员变量的初始化(Integral type)  
    const int BClass::csi = 1; // 静态常量成员变量的初始化(Integral type)  
    const double BClass::csd = 99.9; // 静态常量成员变量的初始化(non-Integral type
静态成员属于类作用域,但不属于类对象,和普通的static变量一样,程序一运行就分配内存并初始化,生命周期和程序一致。
所以,在类的构造函数里初始化static变量显然是不合理的。
静态成员其实和全局变量地位是一样的,只不过编译器把它的使用限制在类作用域内(不是类对象,它不属于类对象成员),要在类的定义外(不是类作用域外)初始化。

下面再说说成员变量是引用的情况:

因为引用是别名的意思,所以定义应用肯定是外部有定义,然后在构造函数初始化列表中被初始化的。

如果两个类要对第三个类的数据进行共享处理,可以考虑把第三个类作为这两个类的引用类型的成员变量。

你可能感兴趣的:(c++)