本文共 2169 字,大约阅读时间需要 7 分钟。
智能指针和异常
即时程序块过早结束,智能指针类也能确保在内存不再需要时将其释放void f(){ shared_ptr sp(new int(42)); //分配一个新对象 //这段代码抛出一个异常,且在f中未被捕获} //在函数结束时shared_ptr自动释放内存
与之对应的,当发生异常时,我们直接管理的内存是不会自动释放的。如果使用内置指针管理内存,且在new之后在对应的delete之前发生了异常,则内存是不会被是释放的。
void f(){ int *ip = new int(42); //动态分配一个新对象 //这段代码抛出异常,且在f中未捕获 delete ip; //在退出之前释放内存}
如果在new和delete之间发生异常,且异常未在f中被捕获,则内存就永远不会被是释放了。在函数f之外没有指针指向这块内存
智能指针和哑类
假如,我们正在使用一个C/C++都使用的网络库,代码如下:struct destination; //表示我们正在连接着什么struct connection; //使用连接所需信息connection connect(destination *); //打开连接void disconnect(connection); //关闭给定连接void f(destination &d /*其他参数*/){ //获得一个连接,记住使用完要关闭它 connection c = connect(&d); //使用连接 //如果我们在f退出前忘记调用disconnect,就无法关闭c了}
对于这个问题,我们使用share_ptr来保证connection被正确关闭
当一个shared_ptr被销毁时,它默认地对它管理地指针进行delete操作。为了用shared_ptr来管理一个connection,我们必须首先定义一个函数来代替delete。这个删除器函数必须能够完成对shared_ptr中保存的指针进行释放操作。在本例中,我们的删除器必须接受单个类型为connection*的参数。void end_connection(connection *p){ disconnect(*p);}
当我们创建一个shared_ptr时,可以传递一个指向删除器函数的参数
void f(destination &d /*其他参数*/){ connection c = connect(&d); shared_ptrp(&c, end_connection); //使用连接 //当f退出时,connection会被正确关闭}
当p被销毁时,它不会对自己保存的指针执行delete,而是调用end_connection。end_connection会调用disconnect,从而确保连接被关闭。如果发生了异常,p同样会被销毁,从而连接被关闭
编写自己版本用shared_ptr管理connection的函数,并用lambda代替end_connection函数
#include#include using namespace std;struct destination { };struct connection { };connection connect(destination* pd) { cout << "打开连接" << endl; return connection();}void disconnect(connection c) { cout << "关闭连接" << endl;}//未使用shared_ptr的版本void f(destination& d) { cout << "直接管理connect" << endl; connection c = connect(&d); //忘记调用disconnect关闭连接 cout << endl;}void end_connection(connection* p) { disconnect(*p); }//lambda不捕获局部变量,参数为connection指针,用改指针指向的对象调用disconnect即可//[](connection *p){disconnect(*p);}void f1(destination& d) { cout << "用shared_ptr管理connect" << endl; connection c = connect(&d); shared_ptr p(&c, end_connection); //shared_ptr p(&c,[](connection *p){disconnect(*p);} ); //忘记调用disconnect关闭连接 cout << endl;}int main() { destination d; f(d); f1(d); return 0;}
转载地址:http://dtxmb.baihongyu.com/