C++中对象的构造顺序
2019-05-23 09:53:49来源:博客园 阅读 ()
1,C++ 中的类可以定义多个对象,那么对象构造顺序是怎样的?
1,很多的 bug 是由对象的构造顺序造成的,虽然它不难;
2,对象的构造往往和构造函数牵涉在一起,构造函数的函数体又可能由非常复杂的程序逻辑组成的;
3,这样就有可能引入了一个问题,不同类的它们的构造函数中的程序逻辑也许是相互依赖的,当这种相互依赖一旦发生,那么对象的构造顺序就很可能导致程序中非常难以调试的 bug 出现;
4,在工程中,由于对象的构造顺序而造成的软件 bug 非常之多,因此有必要梳理下对象的构造顺序;
2,对于局部对象:
1,当程序执行流到达对象的定义语句时进行构造;
1,构造时调用构造函数;
3,局部对象的构造顺序实例分析:
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 14 Test(const Test& obj) 15 { 16 mi = obj.mi; 17 printf("Test(const Test& obj): %d\n", mi); 18 } 19 }; 20 21 int main() 22 { 23 int i = 0; 24 Test a1 = i; // 第一个被构造的对象 25 26 while( i < 3 ) 27 { 28 Test a2 = ++i; // 第二个被构造的对象;反复的被构造三次对象; 29 } 30 31 // goto End; // 下面的输出不会执行了;程序执行流跳过了程序调用的定义,则对象就没有被构造了; 32 if( i < 4 ) 33 { 34 Test a = a1; // 第三个被构造的对象;Test(const Test& obj): 3 35 } 36 else 37 { 38 Test a(100); 39 } 40 // End: 41 return 0; 42 }
2,这个实验说明:
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 14 Test(const Test& obj) 15 { 16 mi = obj.mi; 17 printf("Test(const Test& obj): %d\n", mi); 18 } 19 20 int getMi() 21 { 22 return mi; 23 } 24 }; 25 26 int main() 27 { 28 int i = 0; 29 Test a1 = i; // Test(int i): 0 30 31 while( i < 3 ) 32 { 33 Test a2 = ++i; // Test(int i): 1, 2, 3 34 } 35 goto End; 36 Test a(100); // 这里程序执行流跳过了对象的定义,因此 a 这个对象是没有被构造的,没有被构造意味着 a 这个对象它的状态是没有被初始化的,如果后面使用这个对象,则会产生灾难性的错误;g++ 可以帮助我们报出这个错误,但是其它编译器有可能不能,因为这不是标准,比如 Visual Studio 中的编译器; 37 End: 38 printf("a.mi = %d\n", a.getMi()); // 这里打印随机值;a 对象没有被初始化,因为构造函数没有被调用; 39 40 return 0; 41 }
2,这个实验说明:
1,对象的构造如果不是显示的调用,则只发生在对象定义(运行时)之时;
2,编译时只产生没有初始化的对象(这里很模糊,不清楚);
3,程序执行流和程序的编译不相关,编译还是会都编译的。执行确定了构造函数的调用,而编译则是生成空间;
4,对于堆对象:
1,当程序执行流到达 new 语句时创建对象;
1,创建对象就要触发构造函数的调用;
2,其实堆对象构造顺序也和程序执行流相关,只不过说由于引入了 new 关键字,堆对象的构造顺序比局部对象更容易确认些;
2,使用 new 创建对象将自动触发构造函数的调用;
5,堆对象的构造顺序编程实验:
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 14 Test(const Test& obj) 15 { 16 mi = obj.mi; 17 printf("Test(const Test& obj): %d\n", mi); 18 } 19 20 int getMi() 21 { 22 return mi; 23 } 24 }; 25 26 int main() 27 { 28 int i = 0; 29 Test* a1 = new Test(i); // Test(int i): 0 30 31 while( ++i < 10 ) 32 if( i % 2 ) 33 new Test(i); // Test(int i): 1, 3, 5, 7, 9 34 35 if( i < 4 ) 36 new Test(*a1); 37 else 38 new Test(100); // Test(int i): 100 39 40 return 0; 41 }
1,堆对象的创建也会受到 goto 语句的影响,因为 goto 语句会改变程序执行流,也就可能绕过堆对象的创建;
6,对于全局对象:
1,全局对象的构造顺序是不确定的;
1,这里带来的 bug 是非常多的;
2,C++ 标准没有定义全局对象的构造顺序;
2,不同的编译器使用不同的规则确定构造顺序;
7,全局对象的构造顺序:
1,test.h文件:
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
2,t1.cpp 文件:
1 #include "test.h"
2
3 Test t1("t1");
3,t2.cpp 文件:
1 #include "test.h"
2
3 Test t2("t2");
4,t3.cpp 文件:
1 #include "test.h"
2
3 Test t3("t3");
5,主函数:
1 #include "test.h" 2 3 Test t4("t4"); // 全局对象的构造一定会在 main 函数之前完成,和程序执行流没有关系;main() 函数执行之前,没有程序执行流的概念,如果出现多个全局对象的时候,它们的构造顺序就不确定了;尤其是两个不同的操作系统更是不同; 4 int main() 5 { 6 Test t5("t5"); 7 }
1,在以后的开发过程中,要避免全局对象之间的相互依赖;
2,当今的软件开发领域,尽量的不使用全局变量的,其中原因之一就是全局的变量它们的初始化顺序是不确定的,面向对象领域就变成了全局对象的构造顺序是不确定的;
3,goto 语句也是禁用的,因为它会改变程序执行流,这样会造成局部对象构造顺序产生错乱,有可能导致程序里面局部对象构造出现问题,进而产生不可预计的灾难性错误;
8,小结:
1,局部对象的构造顺序依赖于程序的执行流;
2,堆对象的构造顺序依赖于 new 的使用顺序;
3,全局对象的构造顺序是不确定的;
原文链接:https://www.cnblogs.com/dishengAndziyu/p/10906308.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:C++中的深拷贝和浅拷贝构造函数
- C++ 转换函数搭配友元函数 2020-06-10
- C++ 自动转换和强制类型转换(用户自定义类类型) 2020-06-10
- C++ rand函数 2020-06-10
- C++ 友元函数 2020-06-10
- C++ 运算符重载 2020-06-10
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash