您的位置:首页 > 编程语言 > C语言/C++

Effective C++ 对象管理资源

2014-04-03 22:49 309 查看
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;
}



在程序中,我们使用了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函数。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息