21,对象的构造顺序

好多bug由对象构造造成--------对象的构造与构造函数有关系

1. 对象的构造顺序

—C++中的类可以定义多个对象,那么对象构造顺序是怎样的?

(1)对于局部对象:当程序执行流到达对象的定义语句进行构造。   对象定义--->构造---->调用构造函数

 1 #include<stdio.h>
 2 
 3 class Test
 4 {
 5 private:
 6     int mi;
 7 public:
 8     Test(int i)   //构造函数
 9     {
10         mi = i;
11         printf("Test(int i) : %d\n",mi);
12     }
13     Test(const Test& obj)    //拷贝构造函数
14     {
15         mi = obj.mi;
16         printf("Test(const Test& obj) : %d\n", mi);
17     }
18 
19     /*
20     int getMi()
21     {
22         return mi;
23     }
24     */
25 };
26 
27 int main()
28 {
29     int i = 0;
30     Test a1 = i;        // 对象构造    Test(int i) :0
31 
32     while (i < 3)
33     {
34         Test a2 = ++i;   //对象的定义,那么就有对象构造3次      Test(int i) :1,2,3
35     }
36 
37     if (i < 4)
38     {
39         Test a = a1;   //对象的定义,那么就有对象拷贝构造      Test(const Test& obj) : 0
40     }
41     else
42     {
43         Test a(100);
44     }
45 
46     /*
47 goto End;  不能非法改变程序的执行流
48 
49            Test a(100);               //a没有构造,初始化,后面不能使用
50 End:
51             printf("a.mi=%d\n",a.getMi());   //没有初始化对象,没有调用构造函数,有的编译器会输出随机值
52 
53     */
54     return 0;
55 }

(2)对于堆对象

  ①当程序执行流到达new语句创建对象

  ②使用new创建对象自动触发构造函数的调用

 1 #include<stdio.h>
 2 
 3 //堆对象的构造顺序    Test* a1 = new Test(i);  
 4 
 5 class Test
 6 {
 7 private:
 8     int mi;
 9 public:
10     Test(int i)    //构造函数
11     {
12         mi = i;
13         printf("Test(int i) : %d\n", mi);
14     }
15     Test(const Test& obj)    //拷贝构造函数
16     {
17         mi = obj.mi;
18         printf("Test(const Test& obj) : %d\n", mi);
19     }
20 
21 };
22 
23 int main()
24 {
25     int i = 0;
26     Test* a1 = new Test(i);                 //Test(int i) : 0
27 
28     while (++i < 10)
29         if (i % 2)
30             new Test(i);                    //Test(int i) : 1,3,5,7,9
31 
32     if (i < 4)
33         new Test(*a1);                    
34 
35     else
36         new Test(100);                      //Test(int i) :100
37 
38     return 0;
39 }

(3)对于全局对象

  ①对象的构造顺序不确定的

  ②不同的编译器使用不同的规则确定构造顺序

//test.h

复制代码
#ifndef _TEST_H_
#define _TEST_H_
#include<stdio.h>
 
class Test
{
public:
    Test(const char* s)
    {
        printf("%s\n", s);
    }
}; 
#endif
复制代码

//t1.cpp


Test t1("t1");//全局变量

//t2.cpp

#include "test.h"
Test t2("t2");//全局变量 //t3.cpp #include "test.h"
Test t3("t3");//全局变量
复制代码

//main.cpp

复制代码
#include <stdio.h>
#include "test.h"

//注意:全局变量会先于main函数执行,因此

//4个全局变量t1-t4会被先构造,再其顺序是不确定的,

//要依赖于编译器。 那么不同的编译器使用不同的规则确定全局变量的构造顺序

//当构造完全局对象后,会执行main函数,可以发现

//t5是最后一个被构造的。

Test t4("t4"); //全局变量  他的构造在main()之前
 
int main()
{
    Test t5("t5"); //局部对象,他的构造按照程序执行流
    return 0;
}
复制代码

g++编译器的输出结果:

//实验1:g++ main.cpp t1.cpp t2.cpp t3.cpp

//t3->t2->t1->t4->t5:  从右向左

//实验2:g++  t3.cpp t1.cpp main.cpp t2.cpp

//t2->t4->t1->t3->t5:  从右向左

2.小结

(1)局部对象构造顺序依赖于程序的执行流

(2)堆对象构造顺序依赖于new的使用顺序

(3)全局对象构造顺序是不确定的



猜你喜欢

转载自www.cnblogs.com/liuyueyue/p/13372577.html