c++编程实践—如何理解生命周期

一、生命周期

生命周期,Lifetime,就是一个事物从出现到结束的全过程的时间范围。生命周期这个概念对于传统的C++程序员来说,其实并不那么清晰。它不如其它语言如java,C#以及新出现的Rust等语言中,都有明确的时间周期的相关分析说明。因为在这些语言中,资源的管理都是隐式的,即由垃圾回收器或运行时进行。这对于开发者来说,可以认为是一种福音。所以它们对于程序员来说,需要明确生命周期的全过程。

但c++这类语言是相信开发者的,生命周期完全交给开发者,由开发者自行进行生命周期的管理。这就带来了致命的问题,并不是所有的开发者,都是一个合格的资源的生命周期管理者。即使是合格的开发者,也可能因为各种意外导致生命周期管理的异常。这就意味着资源的泄露或者说崩溃。

二、c++中的生命周期

c++之所以为开发者诟病,一个重要原因是资源的管理,包括但不限制最重要的内存资源。具像化出来,就是指针的操作。资源的应用,必须在其生命周期的可用用范围内。如果在之外,要么返回一个错误值,但更大的可能直接就崩溃了。

c++开发中,资源的种类有很多,如变量、指针、内存、句柄、io等等。表现形式也五花八六,光内存就可以有缓冲、内存池、对象等等。这也让很多的初学者感到迷惑。其实,对于绝大多数的资源,基本都可以划到内存资源中来。比如对象和句柄,往往其内部就是一块的内存。

c++中内存的分配和回收有很多种机制,可以是栈(自动操作)、堆(手工分配),也可以表现为类的构造和析构函数。不同的表现情况,可能需要不同的处理机制和注意点。这在前面的相关细节的分析中都反复的说明过。

一般来说,c++的生命周期还是可以通过下面的不同情况来进行较为明确的划分:

  1. 自动存储对象生命周期
    它主要是栈对象,主要就是函数内部的临时变量、参数;代码块内的临时变量以及其它一些特定情况下的临时对象(如拷贝或返回值中的临时变量)等。它的生命周期由编译器和运行时自动进行管理,效率非常高。它的生命周期基本是从声明开始到作用域结束也就是结束了
  2. 静态存储对象生命周期
    这种对象包括全局变量、静态变量。它的生命周期一般也是自动由编译器和运行进行管理,其生命周期贯穿整个程序的生命周期,它在main函数前创建在程序结束时结束
  3. 动态存储对象生命周期
    这是c++程序员最复杂的生命周期管理,它包括各种对象、变量以及内存指针等。其生命周期由开发者全权负责。它一般从new/malloc分配开始,到delete/free时结束。这种对象的生命周期复杂多变,而且受到各种意外情况的干涉(比如接口暴露出一个指针,应用方给释放了)。所以在这种情况下,一般建议是使用智能指针来操作,尽可能防止出现意外

三、生命周期的意义

需要跳出来说一下。生命周期是爱其它依赖影响的。比如,一块分配的内存依赖于一个进程管理,而一个进程依赖于操作系统,而操作系统又依赖于硬件。当强制关闭电源时,相关的所有生命周期自然就结束了。所以,这里的讨论和分析其实就是基于正常的标准情况下的分析。

生命周期核心就是资源管理,而资源对于计算机来说,对于需求来说,是永远不会满足的。原来一个游戏有个几百M就很大了,后来到G,而现在动辙就几十G

。c++没有垃圾回收,没有如Rust那样强制的所有权管理进行间接的生命周期管理。所以,其对资源的安全应用以及分配回收就成为了一个头等重要的问题。c++语言先是提供了RAII的资源管理机制,又在新标准中提供了智能指针,但这都无法从整体上控制开发者对资源的安全管理。因此,对于c++开发者来说,资源的生命周期的管理,仍然是一个极其重要的问题。

四、新标准的发展

随着c++11及之后的标准的快速迭代和演进,新的对于生命周期的控制或者说对资源管理的机制不断推出。如移动语义、各种智能指针。特别是在c++17中提供了std::launder,用于在延长同一内存的对象更换(不满足透明可替换),而在c++23中则提供了显式的生命周期管理如std::start_lifetime_as

应用显式的告诉编译器一个对象启动了。这两个函数在前面都有过详细的分析说明,不清楚的可以回头翻一下。

也就是说,c++的新标准的发展,一定是强生命周期、显式生命周期的管控为方向,尽量减少或控制隐式生命周期的处理。不同的场景下,对效率和性能的要求不同,而通过对象生命周期的动态管理,可以有效的提高性能和效率(如移动 语义和刚刚的两人个函数)。

五、总结

从原则上来讲,生命周期越是自动控制或显式可控就越简单方便。但对于c++这种语言来说,不太符合实际情况。所以针对资源,特别是内存,一般是首选RAII,在新标准中强烈推荐使用智能指针来管理堆内存,并严格厘清不同智能指针的应用场景。对于一些可将临时对象的生命周期进行延长的技术手段要谨慎使用(如绑定到右值引用或const左值引用等)。

总体上来说,生命周期对于c++来说是一种极其灵活的存在,开发者要善于通过各种技术手段来限制生命周期的范围,不能任意的延长或缩短资源的生命周期。所谓恰到好处,正是如此!

相关推荐
FlightYe10 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频
by2099911 小时前
C++ 智能指针的所有权与使用
开发语言·c++·经验分享
Rover Ramble11 小时前
C++ 用互斥锁实现读写锁
开发语言·c++
你怎么知道我是队长11 小时前
C++零基础入门第2周:数据类型、运算符与表达式完全指南(附20段可运行代码+避坑清单)
c++
say_fall12 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
雪落漂泊12 小时前
C++算法 滑动窗口篇(下)
开发语言·c++
你怎么知道我是队长15 小时前
C++零基础第3周:if/else、switch、for/while/do-while 控制流完全指南(附20段可运行代码+避坑清单)
java·开发语言·c++
青少儿编程课堂16 小时前
蓝桥杯·全国青少年信息素养大赛·电子学会Python/C++考级:倍增法求最近公共祖先LCA解析
c++·python·算法·bfs·信息学竞赛
雷✘16 小时前
C++ 类与对象的初始化机制、成员访问边界与拷贝优化
java·网络·c++
努力实干17 小时前
简单工厂模式(Simple Factory Pattern)——C++
开发语言·c++·简单工厂模式