一、生命周期
生命周期,Lifetime,就是一个事物从出现到结束的全过程的时间范围。生命周期这个概念对于传统的C++程序员来说,其实并不那么清晰。它不如其它语言如java,C#以及新出现的Rust等语言中,都有明确的时间周期的相关分析说明。因为在这些语言中,资源的管理都是隐式的,即由垃圾回收器或运行时进行。这对于开发者来说,可以认为是一种福音。所以它们对于程序员来说,需要明确生命周期的全过程。
但c++这类语言是相信开发者的,生命周期完全交给开发者,由开发者自行进行生命周期的管理。这就带来了致命的问题,并不是所有的开发者,都是一个合格的资源的生命周期管理者。即使是合格的开发者,也可能因为各种意外导致生命周期管理的异常。这就意味着资源的泄露或者说崩溃。
二、c++中的生命周期
c++之所以为开发者诟病,一个重要原因是资源的管理,包括但不限制最重要的内存资源。具像化出来,就是指针的操作。资源的应用,必须在其生命周期的可用用范围内。如果在之外,要么返回一个错误值,但更大的可能直接就崩溃了。
c++开发中,资源的种类有很多,如变量、指针、内存、句柄、io等等。表现形式也五花八六,光内存就可以有缓冲、内存池、对象等等。这也让很多的初学者感到迷惑。其实,对于绝大多数的资源,基本都可以划到内存资源中来。比如对象和句柄,往往其内部就是一块的内存。
c++中内存的分配和回收有很多种机制,可以是栈(自动操作)、堆(手工分配),也可以表现为类的构造和析构函数。不同的表现情况,可能需要不同的处理机制和注意点。这在前面的相关细节的分析中都反复的说明过。
一般来说,c++的生命周期还是可以通过下面的不同情况来进行较为明确的划分:
- 自动存储对象生命周期
它主要是栈对象,主要就是函数内部的临时变量、参数;代码块内的临时变量以及其它一些特定情况下的临时对象(如拷贝或返回值中的临时变量)等。它的生命周期由编译器和运行时自动进行管理,效率非常高。它的生命周期基本是从声明开始到作用域结束也就是结束了 - 静态存储对象生命周期
这种对象包括全局变量、静态变量。它的生命周期一般也是自动由编译器和运行进行管理,其生命周期贯穿整个程序的生命周期,它在main函数前创建在程序结束时结束 - 动态存储对象生命周期
这是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++来说是一种极其灵活的存在,开发者要善于通过各种技术手段来限制生命周期的范围,不能任意的延长或缩短资源的生命周期。所谓恰到好处,正是如此!