堆,英文是 heap,在内存管理的语境下,指的是动态分配内存的区域。这个堆跟数据结构里的堆不是一回事。这里的内存,被分配之后需要手工释放,否则,就会造成内存泄漏。
C++ 标准里一个相关概念是自由存储区,英文是 free store,特指使用new和delete来分配和释放内存的区域。一般而言,这是堆的一个子集:new和delete操作都是free store区域;malloc和free操作的区域都是heap;但是new和delete操作都是基于malloc与free实现。
比如:
vector<int>* ptr_vector = new vector<int>();
栈,英文是 stack,在内存管理的语境下,指的是函数调用过程中产生的本地变量和调用数据的区域。这个栈和数据结构里的栈高度相似,都满足“后进先出”(last-in-first-out 或 LIFO)。
RAII,完整的英文是 Resource Acquisition Is Initialization,是 C++ 所特有的资源管理方式。有少量其他语言,如 D、Ada 和 Rust 也采纳了 RAII,但主流的编程语言中, C++ 是唯一一个依赖 RAII 来做资源管理的。
RAII(Resource Acquisition Is Initialization)机制是Bjarne Stroustrup首先提出的,是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。
比如我们在C++中经常使用new申请了内存空间,但是却也经常忘记delete回收申请的空间,容易造成内存溢出,于是RAII技术就诞生了,来解决这样的问题。
void Func()
{
FILE *fp;
char* filename = "test.txt";
if((fp=fopen(filename,"r"))==NULL)
{
printf("not open");
exit(0);
}
... // 如果 在使用fp指针时产生异常 并退出
// 那么 fp文件就没有正常关闭
fclose(fp);
}
此时,就可以让RAII惯用法大显身手了。
RAII的实现原理很简单,利用stack上的临时对象生命期是程序自动管理的这一特点,将我们的资源释放操作封装在一个临时对象中。
具体示例代码如下:
class Resource{};
class RAII{
public:
RAII(Resource* aResource):r_(aResource){} //获取资源
~RAII() {delete r_;} //释放资源
Resource* get() {return r_ ;} //访问资源
private:
Resource* r_;
};
void UseResources()
{
// 获取资源1
// ...
// 获取资源n
// 使用这些资源
// 释放资源n
// ...
// 释放资源1
}