C++程序中最常用的资源包括动态分配的内存,文件描述器,互斥锁,数据库连接,网络socket等等。不论哪种资源,重要的是,当你不再使用他时,必须将他归还给系统。

一个很好的做法是以对象管理资源。把资源放进对象内,我们便可依赖C++的析构函数自动调用机制确保资源被释放,这样便不会发生资源泄露的问题。一个实现的方法是,以智能指针封装资源,由于atuo_ptr缺陷太多,已经基本被废弃,建议使用shared_ptr。下面看一个使用shared_ptr的具体实现


  1. void f()
  2. {
  3. shared_ptr<Investment> pInv(createInvestment());//工厂函数返回的对象初始化资源,再用shared_ptr封装他
  4. }

shared_ptr的一个特性是其提供了引用计数,每当其管理对象被指向便会+1,在无人指向它时自动删除该资源,并且支持copy操作。因为可以很方便的通过它进行内存管理,不用担心资源泄露。

在资源管理类中小心copying行为

一般情况下,对资源的复制行为是不会允许的,比如互斥锁,你不会想要把一个互斥器对象复制的,对吧?所以如果你的资源对象不适合被复制,你应该禁止复制这种行为:把copying操作声明为private,然后继承它,就像下面这样


  1. class Lock:private Uncopyable
  2. {
  3. ...
  4. };

或者如果你确实有需求复制资源,例如你非得复制互斥器,那就使用前面介绍的shared_ptr吧,但是shared_ptr有一个不幸的特性,当引用次数为0时删除其所指物,不过类似于C++标准库里的其他部件,shared_ptr允许你定制自己的删除器,shared_ptr有一个重载类型接受第二个参数。


  1. Class Lock
  2. {
  3. public:
  4. explicit Lock(Mutex* pm):mutexPtr(pm,unlock)//第二个参数指定引用计数为0时的行为,即是unlock
  5. {
  6. lock(mutexPtr.get());//mutexPtr.get()返回mutexPtr管理对象的原生类型
  7. }
  8. private:
  9. shoread_ptr<Mutex> mutexPtr;
  10. };

在资源管理类中提供对原始资源的访问也是一个重要的功能。

对于share_ptr,它提供了get()成员函数,用来执行显式转换,返回智能指针内部的原始指针

对与我们自定义资源管理类,有两种方式提供对原始资源的访问:显式转换函数和隐式转换函数


  1. //假设我们有这样一个类
  2. class Font
  3. {
  4. public:
  5. explicit Font(FontHandle fg):f(fh){}
  6. private:
  7. FontHandle f;
  8. };

其显式转换函数形式为

FontHanld get() const { return f; }

其隐式转换函数形式为

operateor FontHandle() const { return f; }

这两种形式各有好处,隐式转换的好处是比较自然,但是会增加错误发生机会,例如我们本想得到一个Font,结果却意外得到FontHandle


  1. Font f1(getFont());
  2. FontHandle f2=f1;//这里会将Font转型为FontHandle,假如这不是你想要的呢?这个错误很隐蔽

在使用智能指针时会发生一个问题,如果有一个函数是以下形式:

process( shared_ptr<Investment> (new Investment),priority );

这条语句有三个动作:

调用unlock,执行new Investment,调用shared_ptr构造函数。我们知道,new Investment动作一定在shared_ptr构造函数之前,另外C++对构造函数内动作的次序是无定义的,如果unlock动作发生在第二顺位,并且如果它的调用导致异常,此时new Investment返回的指针会遗失,引发资源泄露。对此,解决方法是先建立好智能指针。


  1. shared_ptr<Investment> p(new Investment);
  2. process(p,priority);

总结起来便是,以独立语句将newed对象置入智能指针。

最新文章

  1. poj1006 / hdu1370 Biorhythms (中国剩余定理)
  2. JS数组键值,数组合并,
  3. Spring—Quartz定时调度CronTrigger时间配置格式说明与实例
  4. Windows 10 解决 0x80070021 错误
  5. usb库文件usb_desc.c分析
  6. Expression&lt;Func&lt;T,TResult&gt;&gt;和Func&lt;T,TResult&gt; 与AOP与WCF
  7. 20151120 jsp相关
  8. css3动画工具
  9. 记录下关于SQL Server的东西
  10. AI 人工智能 探索 (三)
  11. Java容器---Map基础
  12. Sequelize 基本操作
  13. Spring Cloud 入门教程 - Eureka服务注册与发现
  14. PHP学习笔记 02 之文件上传
  15. WebSocket刨根问底(二)
  16. [转]js 取得 Unix时间戳(Unix timestamp)
  17. 数据备份、pymysql模块
  18. PHP实现简单发红包(随机分配,平均分配)
  19. Concordion test
  20. 如何在Android的ListView中构建CheckBox和RadioButton列表(支持单选和多选的投票项目示例)

热门文章

  1. anyconnect connection attempt has failed
  2. [译文][转载]greenlet:轻量级并发程序
  3. Linux 实时查看进程网络的使用情况
  4. 集群、RAC和MAA
  5. 转:Java中的cas
  6. 如何分析Mysql慢SQL
  7. Django templates加载css/js/image等静态资源
  8. 对QP中RTC的理解
  9. Linux重启命令介绍
  10. python网络编程之协程