Effective C++ 对象管理资源

Effective C++ 看完资源管理章节,做了一些简单的总结,并且实现了书中提到的一些做法。

首先,在C++中,资源是多种多样的,包括new的内存,互斥锁,IO设备等等,应用程序在占用完该设备之后都应该将设备交换给系统。
可是在实际的应用程序中做到这一点是很难的,即使自己已经考虑了各种细节,也很难避免,比如下面的例子:

class Management{...};
Management *createManagement()
{
    return Management(); //为了简单,假设Management类具有一个默认构造函数
}
void f()
{
    Management *ptr = createManagement();
    ......
    delte ptr;
}
如果在.....部分出现了异常,或者是一个出人意料的return语句,将会直接导致ptr指向的资源泄漏,更严重的是,ptr对象指向的资源也会泄漏。


因此,如果有一个负责“资源管理”的对象,那么我们就可以将“资源泄漏”的危机移交给这样的对象了(至少在很大程度上是这样)。
所幸的是,在C++中存在auto_ptr , shared_ptr这样的指针,可以用来封装需要管理的对象指针,而用户不需要担心在什么时候调用delete。什么时候需要释放资源了。
PS:auto_ptr保证某资源在任何时候只有一个指针指向它,因此,“赋值”对于auto_ptr来说,是移交了资源的管理权。
shared_ptr则是使用“reference_counting”来标志当前的资源是否可以被释放,即如果指向当前资源的指针计数为0的话,那么则可以释放该资源。
下面的程序简要的介绍了使用auto_ptr以及shared_ptr的使用方法,

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <assert.h>
#include <memory>

using namespace std;
//using namespace boost;

class Management
{
private:
	int money;
public:
	Management(int _money = 0 ):money(_money){}
	~Management(){}
	void get_money(){cout <<  money << endl;}
};

Management *getManagement(int _val = 0)
{
	return new Management(_val);
}

int main()
{
	Management *ptr = getManagement(10);
	ptr->get_money();
	delete ptr;
	

	cout << "auto ptr..." << endl;
	auto_ptr<Management> pMa(getManagement(20));
	pMa->get_money();
	auto_ptr<Management> pMa2 = pMa;
	//pMa->get_money(); //error!! pMa已经交出了资源的管理权
	pMa2->get_money();
	
	cout << "shared ptr..." << endl;

	shared_ptr<Management> spMa(getManagement(20));
	spMa->get_money();
	(*spMa).get_money();
	shared_ptr<Management> spMa2 = spMa;
	spMa->get_money();
	spMa2->get_money();

	return 0;
}
Effective C++ 对象管理资源_第1张图片

在程序中,我们使用了shared_ptr封装了指针,但是如果在实际的应用中,我们需要Management指针怎么办,所幸的是shared_ptr的get函数用来提取该指针实际的类型。

即:

shared_ptr<Management> spMa(getManagement(20));
void f(Management *);
//call function f
f(ptr.get()); //get()函数提取出实际隐含的类型


PS:shared_ptr也重载了指针访问操作符-> 以及 *操作符。很多时候可以直接使用。见上述程序对get_money()的调用。


shared_ptr会在引用计数为0的时候删除该指针,这并不能满足所有的应用。比如:互斥锁,我们在使用完互斥锁之后,并不是要释放它,只是解锁unlock而已,因此我们就需要定义自己的资源管理类,如下定义了自己的mutex互斥锁资源管理类。

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <thread>
#include <assert.h>
#include <mutex>
#include <memory>

using namespace std;
//using namespace boost;

// define own resource Management class
void unlock(mutex *MutexPtr)
{
	cout << "unlock ..." << endl;
	MutexPtr->unlock();
	cout << "unlock end ..." << endl;
}

class Lock
{
public:
	explicit Lock(mutex *pm):MutexPtr(pm,unlock) //unlock函数在引用基数为0时调用函数unlock
	{
		cout << "Lock construction..." << endl;
		(MutexPtr.get())->lock(); //the parameter of lock is a pointer of Mutex
		cout << "Lock contruction end..." << endl;
	}

private:
	shared_ptr<mutex> MutexPtr; 
};



int main()
{

//shared_ptr point to the array is not a good choice. will leak memory

//	boost::shared_ptr<int> p2Arr(new int[10]);
	mutex pt1;
	{
		Lock lock1(&pt1);
	}
	return 0;
}
PS:上述代码编译需要C++11。

shared_ptr默认在引用计数为0的时候删除该指针,也可以显式地指定该函数。如上述程序中的unlock函数。





你可能感兴趣的:(C++,effective,智能指针,shared_ptr,资源管理)