1、为什么要以对象管理资源,它解决什么问题?
考虑下面的需求,客户需要一个动态分配的资源。我提供一个工厂方法,返回一个指针,指向资源。那么问题来了,谁来释放资源呢?只有客户知道什么时候不再使用资源,因此,应该是客户负责释放资源。如果客户没有成功释放资源,造成资源泄漏,注意,这里泄漏的资源不光是一块内存,还可能包括这块内存保存的其他资源。把成功释放资源的希望,寄托在客户身上,显然是不靠谱的。因为:a、客户可能忘记delete;b、代码异常,导致没有执行到delete。
2、它是如何解决这个问题的?
我们知道,栈上分配的对象有个特点,超出作用域,不管什么情况,都会自动调用析构方法。因此,可以把堆上获取的资源,放入栈上的对象中,栈上对象的析构方法,进行delete操作,释放资源。相当于对获取的指针,进行封装。
3、以对象管理资源有两个关键想法:
a、获取资源后,立刻放入栈上的管理对象内,也就是RAII(Resource Acquisition Is Initialization);
b、栈上的管理对象超出作用域,无论出现什么情况,必定调用析构方法,释放资源。
4、这个管理对象类似指针,叫做智能指针。有两个典型的智能指针:auto_ptr和shared_ptr。auto_ptr会导致拥有权的转移,shared_ptr可以共享一个资源。
5、需要注意:auto_ptr和shared_ptr,在析构方法中,执行的是delete,而不是delete[]。这意味着,千万不要使用auto_ptr和shared_ptr管理动态分配的数组。
6、再仔细考虑下开头提出的需求,返回一个资源,期望客户进行封装,那还不如我自己封装好,返回给客户呢。我返回一个管理对象,用它初始化客户端的一个管理对象,注意:客户端的管理对象,只是一个副本。但是,他们中的指针都指向同一块内存。而且,管理对象之间的copy构造成本很低,就是保存同一个指针值,指向同一块内存。