优雅的设计之局部资源管理

局部资源管理(what)

在c++的设计中,对于资源的管理是非常重要的,一旦管理不好就会容易导致内存泄漏,从而出现严重的问题,c++之父引入了资源管理的手法,名叫RAII,它是“Resource Acquisition Is Initialization”的首字母缩写。也称为“资源获取就是初始化”,是c++等编程语言常用的管理资源、避免内存泄露的方法。它保证在任何情况下,使用对象时先构造对象,最后析构对象。资源的获取代码在构造函数中写,资源的释放在析构函数中写。

为什么这样设计(why)

我们都知道,c++这门编程语言的一项难点就是对于内存等资源的管理,我们使用的内存主要是堆内存和栈内存,栈内存的管理是自动的,不需要我们的主动申请与释放,但堆内存可是个麻烦的家伙。堆内存需要我们自己开辟与释放,相对更灵活,但也带来了很多麻烦,如果忘记释放,很容易就造成内存泄漏,内存泄漏的危害就不在这里展开讲了。
作为负责人的程序员,在写c++程序的时候,对堆内存的申请都要做到以下三步:

1.申请堆内存
2.使用
3.释放堆内存

但往往工程量大起来就容易忘记释放,而且更重要的一点是,如果在使用过程中发生了异常,将会中断程序,也就不会对内存进行释放了,这更严重的导致了内存泄漏的问题,所以设计者就想能不能自动的对堆内存进行释放呢?
就这样的设计思路产生了RAII,RALL是利用了栈空间自动内存分配的特点,将在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。通过这种方式,我们实际上把管理内存或者资源的任务交给了一个存放在栈空间上的局部对象。

如何做(how)

实现方式很简单且优雅,就是在函数中,将要申请资源的动作放在类的析构函数中,释放资源的动作放在析构函数中,然后构建栈对象,通过栈对象的自动管理,在生命周期内保持资源的使用权,生命周期结束后释放资源的使用权。
举一个例子:

void fun(){
	stu *s = new student();
	doSomething();  //如果在此处发生了异常,则s所指向的内存未得到释放。
	delete s;
}

处理方式:

class RAII{
public:
	RAII(){
	s = new student();
	}
	~RAll(){
	delete s;
	}
	stu * getResoure(){   //对资源的访问入口
	return s;
	}
private:
	stu *s;
};
void fun(){
	RAII r;
	stu *s=r.getResoure();
	doSomething();
}

这样的好处显而易见:
(1)不需要显式地释放资源。
(3)保证了异常安全。
(2)采用这种方式,对象所需的资源在其生命期内始终保持有效。
是不是感觉很熟悉的感觉…我觉得智能指针的设计思想和这种方式的设计思想具有共通性。
写到这里,也是想吐槽一下,java虚拟机真香。。。
当然c/c++的优势也是Java不可代替的。

你可能感兴趣的:(内存管理,exception,c++,raii)