news 2026/4/3 4:13:36

跟我学C++中级篇—静态变量的生命周期控制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
跟我学C++中级篇—静态变量的生命周期控制

一、生命周期

生命周期分析过几次,这里因为讨论这个问题还得再唠叨一下。所以生命周期,就是大家普遍理解的字面意义。一个变量存在的过程时间段,即其从创建到被回收的全过程的时间周期。生命周期非常重要,在C++开发中,悬垂指针(野指针)引起崩溃,就是生命周期的控制出现了问题。还有常见的不允许返回局部变量的指针或引用也是基于这个道理。
在C++的开发中,生命周期的控制有四种类型,一种是由系统控制的生命周期即自动存储期(一般是栈对象),如临时变量;另外一种是由开发者自己控制的动态存储期(堆对象),如普通指针变量;还有一种是静态或全局存储期,如静态变量;最后一种是线程局部存储期,如纯种局部变量。

二、C++中的静态变量和全局变量

在C++开发中,静态和全局变量是无法绕开的一个技术点。一般来说,汇总到生命周期上,静态变量和全局变量都可以归为静态存储期。它包括全局变量、普通静态变量、函数内的局部静态变量 和类成员的静态变量。
静态生命周期的变量,其生命周期的时间一般与整个程序的生命周期保持一致。只不过,创建的时机根据不同的情况有所不同,比如全局变量一般在主函数启动前就已经构建成功,在程序退出时被回收(退出主函数后);而静态变量中的类静态变量在程序启动时创建,在程序退出时回收;函数内的局部静态变量则在首次调用时被创建(也就是前面在单实例中提到的懒汉模式),程序退出时回收。
在静态生命周期的变量应用中,标准对相关的具体细节的定义和描述并不清晰,这就为静态生命周期变量的使用埋下了不少的雷,如前面提到的动态库的全局变量依赖问题。而这种问题,往往很难发现和定位,这就需要开发者从根本上扫除这种现象的出现,来提高代码的健壮性。

三、问题和分析

正如刚刚所说,C++标准对跨编译单元的静态生命周期的定义并不清晰,这就引出了两个重要的问题:

  1. 初始化顺序的问题
    这个在前面分析过,即SIOF(constinit避免SIOF)。在刚刚提到的动态库中的全局变量依赖问题以及不同的编译单元静态变量的互相依赖问题,都有可能随机的产生不可预知的问题,直到崩溃的发生。而标准定义的模糊就需要开发者必须清晰的控制静态生命周期的变量的依赖顺序。保障链接器形成安全稳定的依赖关系。
  2. 析构顺序问题
    析构问题和初始化问题本质是同一类问题。既然初始化的顺序是无法保证的,那么,析构的顺序同样也是无法保障的。这就会产生在相关的静态生命周期变量回收后,未回收的静态生命周期变量引用或调用其的情况,从而导致类似野指针操作的问题。还有一个典型的可能崩溃的例子就是显式调用abort()绕过主函数退出,则相关静态生命周期的变量无法正常析构。
    这就引申出来前面分析过的另外一个问题,在全局或静态变量上使用智能指针,有可能导致二次释放的崩溃现象。究其原因,都是对顺序的依赖出现了问题。看一个小例子:
Demo&getDemo(){staticDemo d;returnDemo;}structTest{//省略};staticTest t;//静态变量t和d依赖的顺序不确定,可能崩溃

再次强调一下,C++标准中对同一编译单元内的静态生命周期的顺序是可控的,即按照定义的顺序先后进行的。这里分析的问题主要是跨编译单元的说明。

四、解决方法

在明白了上述的问题的根源后,就可以有的放矢的解决问题。在C++的编程实践中主要有以下几种:

  1. 将全局部变量统一定义到一个头文件或同个类中集中管理
//global.hinta=0;intb=0;intc=0;intd=getValue();intgetValue(){return8;}
  1. 线程安全推荐使用局部静态变量
//下面为一个类静态成员函数Demo*Demo::getInstance(){staticDemo*pInstance=newDemo();returnpInstance;}
  1. 静态变量只生产不销毁回收
//只创建,不回收,让系统自动销毁staticint*pTest=newint(100);
  1. 视情况引入智能指针管理静态变量
structData{};class SingleIns{public:staticstd::unique_ptr<Data>getInst(){staticstd::unique_ptr<Data>pIns=std::make_unique<Data>();returnstd::move(pIns);//此特地使用了unique_ptr,可以与shared_ptr对比分析一下}};

五、总结

人们总说“细节决定成败”,在这一点上,生命周期的应用就可以验证这句话。悬垂指针的现象估计是多线程开发中,每个遇到过的开发者的头大的问题。这个问题看似只是一个很细小的问题,但引发的结果往往让开发者不可捉摸。这就需要认真的对代码进行分析整理或者使用更好的方法来管理指针来解决这个问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/12 10:21:45

【深度好文】声纳波束形成技术详解:从时域到频域的近场聚焦

【深度好文】声纳波束形成技术详解&#xff1a;从时域到频域的近场聚焦 摘要&#xff1a;在声纳信号处理中&#xff0c;波束形成&#xff08;Beamforming&#xff09;是核心技术之一。传统的波束形成往往基于远场平面波假设&#xff0c;但在实际应用中&#xff0c;尤其是对于大…

作者头像 李华
网站建设 2026/3/30 23:33:48

AI赋能网络小说创作:脑洞生成的实操指南与技巧

在网络小说创作领域&#xff0c;“脑洞”是作品的核心竞争力——无论是反转不断的剧情、打破常规的设定&#xff0c;还是极具记忆点的人物&#xff0c;都离不开新颖脑洞的支撑。随着AI技术的快速发展&#xff0c;越来越多的创作者开始借助AI工具突破灵感瓶颈&#xff0c;但多数…

作者头像 李华
网站建设 2026/4/1 10:54:46

【从0开始学习Java | 第23篇】动态代理

重阳&#xff0c;来啦&#xff01;第23篇我们聊动态代理——这是Java面试中中高级岗必问、Spring AOP底层核心、MyBatis插件、RPC框架都离不开的知识点。 学会动态代理 直接秒杀 80% 的候选人&#xff01; 一、先搞清楚&#xff1a;到底什么是代理&#xff1f; 生活例子&am…

作者头像 李华
网站建设 2026/4/1 14:44:03

2026AI写小说工具盘点:10款工具从大纲到全篇创作,新手小白也能用

后台私信最多的问题从来不是怎么签约&#xff0c;而是怎么写下去。很多人满怀热情地开了个头&#xff0c;写到第三章就不知道剧情该往哪走了。对着屏幕发呆两小时&#xff0c;最后关掉文档去刷短视频。 这种痛苦我太熟悉了。好在现在是2026年&#xff0c;利用好AI工具&#xf…

作者头像 李华
网站建设 2026/3/28 8:42:53

基于深度学习的商品推荐系统[python]-计算机毕业设计源码+LW文档

摘要&#xff1a;在电子商务蓬勃发展的背景下&#xff0c;商品推荐系统成为提升用户体验和商家销量的关键工具。本文研究并实现了一个基于深度学习的商品推荐系统。阐述了系统的研究背景与意义&#xff0c;介绍了深度学习相关技术&#xff0c;深入分析了系统的功能与非功能需求…

作者头像 李华
网站建设 2026/3/23 7:56:57

什么是 SPoC/MPoC 为什么在SPoC/MPoC 就可用使用即时连接?

SPoC 与 MPoC 安全标准解析 SPoC(Software PIN on COTS)和 MPoC(Mobile Payments on COTS)是 PCI 安全标准委员会(PCI SSC)发布的标准,旨在允许商户在普通的商用智能手机或平板电脑(COTS 设备)上安全地接受支付。之所以强调“即时连接”(或实时监控),是因为 COTS …

作者头像 李华