问题:
C++中的类可以定义多个对象,那么对象的构造顺序是怎么样的?
对象的构造顺序一:
示例如下:
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 main() 21 { 22 int i = 0; 23 Test a1 = i; 24 25 while( i < 3 ) 26 { 27 Test a2 = ++i; 28 } 29 30 if( i < 4 ) 31 { 32 Test a = a1; 33 } 34 else 35 { 36 Test a(100); 37 } 38 39 return 0; 40 }
运行结果如下:
添加上goto语句,运行结果如下:
引入goto使得30-37行的程序被跳过,因此a对象就不会被构造了。
执行流和局部对象的构造息息相关。
非法改变程序的执行流,可能引起灾难性的错误。
示例如下:
我们使用goto跳过了34行,在36行又调用这个a对象,这时编译器就会报错。
g++编译器在这种情况下会报错,但是其他编译器却不一定。
VC下的编译运行结果如下:
可见编译器之间的行为并不一样。
对象的构造顺序二:
示例程序:
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 int getMi() 19 { 20 return mi; 21 } 22 }; 23 24 int main() 25 { 26 int i = 0; 27 Test* a1 = new Test(i); // Test(int i): 0 28 29 while( ++i < 10 ) 30 if( i % 2 ) 31 new Test(i); // Test(int i): 1, 3, 5, 7, 9 32 33 if( i < 4 ) 34 new Test(*a1); 35 else 36 new Test(100); // Test(int i): 100 37 38 return 0; 39 }
运行结果如下:
堆对象的创建也会受到goto语句的影响。
对象的构造顺序三:
全局对象的构造顺序是不确定的。
示例:
1 #ifndef _TEST_H_ 2 #define _TEST_H_ 3 4 #include <stdio.h> 5 6 class Test 7 { 8 public: 9 Test(const char* s) 10 { 11 printf("%s\n", s); 12 } 13 }; 14 15 #endif
1 #include "test.h" 2 3 Test t1("t1");
1 #include "test.h" 2 3 Test t2("t2");
1 #include "test.h" 2 3 Test t3("t3");
1 #include "test.h" 2 3 Test t4("t4"); 4 5 int main() 6 { 7 Test t5("t5"); 8 }
全局对象的构造一定是在main函数执行前完成的,这和程序的执行流没有关系。因为main函数执行前不存在执行流的概念。
如果出现多个全局对象,则他们的构造顺序就不确定了。
运行结果如下:
VC下的编译情况如下:
运行结果如下:
由以上现象可以看到,全局对象的构造顺序是不确定的,不同的编译器是不一样的。
因此,我们在开发的时候要避开全局对象之间的相互依赖。
小结: