前面写过C++的类成员初始化的两种方法。
构造函数内赋值 和 初始化列表…
今天在群里讨论了一种新方法,在此记一下。
首先我们回顾一下,赋值 和 初始化列表两种方法的区别:
http://tkxiong.com/archives/409
然后我们明晰了构造函数的两个阶段…
初始化阶段:
所有类类型的成员都会在初始化阶段被初始化,即使该成员没有出现在构造函数的初始化列表中.
计算阶段:
一般用于执行构造函数体内的赋值操作.
然后我们讨论的新方法是C++11里面的:
1 2 3 4 |
class A { const int a = 3; }; |
这种在类里面直接赋值的方法…(可能部分编译器会报错)
我们讨论的问题是:
- 这个初始化方法对不对,为什么会对…如果不对,为什么不对。
- 这种初始化方法在什么时候执行初始化…
首先第一个问题:
这个初始化方法对不对,为什么会对…如果不对,为什么不对。
上图是用C++11编译的,是没有报错的,所以没有全部截图。
此图是用C++编译的,我们发现它报了警告,显示了应该是 C++11 支持
所以可以得到问题1的结果:
这种初始化方法在C++11里面是正确的。
然后问题2: 它会在什么时候初始化呢
这里我用了这段代码进行测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#include<iostream> using namespace std; class Test1 { public: Test1() : ta(15) { cout << "ta = " << ta << endl; cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; //c尚未赋值前 c = 1; cout << "c = " << c << endl; cout << "Construct Test1" << endl; } Test1(const Test1& t1) { cout << "Copy Construct for Test1" << endl; } Test1& operator = (const Test1& t1) { cout << "assignment for Test1" << endl; return *this; } public: int b = 2; int c; const int a = 10; const int ta = 10; static const int sa = 2; }; class Test2 { public: Test2(Test1& t1) { test1 = t1; } public: Test1 test1; }; int main() { printf("sa = %d\n",Test1::sa); //可以得知static是在类初始化前就初始化了的 Test1 t1; Test2 t2(t1); cout << endl << "Construct Finish!" << endl; cout << "t1.a = " << t1.a << endl; cout << "t1.ta = " << t1.ta << endl; return 0; } |
运行结果如下:
分析结论哈:
- 根据sa可以得出,static是在main之前就初始化了的
- 我们知道类成员在初始化阶段是按成员在类里面定义的顺序初始化的,所以先初始化a,然后初始化ta。然后ta的值显示在初始化列表的值,a的值显示的是我们新的初始化方法的值(暂成为类内初始化),所以我们可以得知,类内初始化 是优先于 列表初始化的
第三点来自于c的值…
我们知道new的操作分为两步,一步是配置空间(类似于malloc),第二步是 初始化…
所以我们可以把前面提到的 构造函数的两步 写成 类初始化四步!
哪四步呢:
- static成员的初始化,在main函数前进行
- 类初始化:配置成员空间,如果有指定值,就赋值。(这里的赋值就是新的初始化方法)
- 构造函数 初始化列表
- 构造函数内 赋值
大致到这里就结束了…
PS.以上所有都是个人的推测,并不是C++11标准…我也没有看过类似的书…全都是自己的臆断…如果有错望指正,如果感觉没错…也不要完全相信…万一错了呢。
构造函数调用顺序:基类构造函数、成员对象的构造函数,子类的构造函数。
析构函数调用顺序与其相反。
【C++】类成员初始化再提