隐藏的坑——C++中局部静态变量的构造析构顺序问题

隐藏的坑——C++中局部静态变量构造析构顺序问题
pgm_430mei要论C++中对象的构造/析构顺序,这是个“⽼问题”了,今番再论,实在是有感⽽发。
⾸先要明确⼀条原则:构造与析构的顺序是相反的。
个⼈总结,在这个知识点的理解和掌握上,有四层“境界”:
辽河油田华宇网
第⼀层:理解⼀个类内部各个数据成员之间的构造/析构顺序。这⾥需要注意的是,数据成员的构造顺序与其在类中声明的顺序相同,⽽⽆论构造函数中初始化列表中的顺序,这个不难;
第⼆层:理解基类和派⽣类之间的构造/析构顺序。这似乎是⼤部分C++书籍着墨最多的知识点,当然也不难掌握;
第三层:理解在函数内部出现的局部变量的构造/析构顺序。同上,也不难掌握;
第四层:理解在⼀个应⽤程序内部,静态变量的构造/析构顺序。其中,对于全局静态变量,视编译器的实现⽽定(⼀种⽅式是根据字母顺序来决定);对于有依赖关系的,那么视依赖关系⽽定。⽽对于局部静态变量来说,问题就开始复杂了。这也正是本⽂论述的重点。
⾸先,要理解编译器是如何实现局部静态变量的语法特性的。从语法上来看,局部静态变量与全局静态变量最⼤的不同在于构造时机——当且仅当程序执⾏路径⾸次达到局部静态变量的定义处才出发构造。注意是⾸次。印象中编译器是通过添加⼀个标识变量(当然这个变量⼀定是全局静态的)来实现的(即每次程序执⾏到时,⾸先检查这个标志变量),如此来确保调⽤时构造且只构造⼀次的特性。那么反过来看局部静态变量的析构,编译器会维护⼀个析构函数的函数指针栈,⼀旦构造完成,就会把相应的析构函数指针放到这个栈中。当程序结束后,由编译器⽣成的doexit函数会逐个调⽤这些析构函数,完成进程结束前的扫尾⼯作。基于此,很显然,对于分布在程序各处的静态局部变量,其构造顺序取决于它们在程序的实际执⾏路径上的先后顺序,⽽析构顺序则正好与之相反。
很简单,不是么?可为什么说是隐藏的坑呢,问题在于:
⼀⽅⾯是因为程序的实际执⾏路径有多个决定因素(例如基于消息驱动模型的程序和多线程程序),有时是不可预知的;
allen试验另⼀⽅⾯是因为局部静态变量分布在程序代码各处,彼此直接没有明显的关联,很容易让开发者忽略它们之间的这种关系(这是最坑的地⽅)。
既然提出问题,那么就讨论应对之道:
(1)最简单的,避免使⽤局部静态变量,将变量的声明周期控制在开发者⼿中;
gal芯片
基本法104条(2)如果确有需要,那么尽量确保局部静态变量之间构造和析构是彼此独⽴互不相关的,换句话说,它们可以以任意的顺序被构造和析构;
再生油嗯……暂时想到以上这些

本文发布于:2024-09-21 01:52:58,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/435087.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:变量   构造   静态   顺序
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议