第三章 资源管理

来源:互联网 发布:淘宝网草根工艺坊 编辑:程序博客网 时间:2024/05/16 05:08

目录:

  • 前言 什么是资源
    • PS 内存泄露的影响
  • 条款13 以对象管理资源
  • 条款14 在资源管理类中小心copying行为
  • 条款15 在资源管理类中提供对原始资源的访问
  • 条款16 成对使用new和delete时要采取相同形式
  • 条款17 以独立语句将newed对象置于智能指针

前言 什么是资源?

资源常指动态分配的内存,也包含互斥锁(std::mutex)、数据库连接以及网络socket等等。不论什么资源,当你不再使用它们时,必须归还给系统
第三章的内容即是说明资源管理的一些方法及注意事项,防止内存泄露

PS: 内存泄露的影响

小程序影响不大。于大程序而言,当内存泄露发生时,系统可用的内存越来越少,程序崩溃且这种情况编译不易发现,进而系统崩溃,接着你就得按重启。对于服务器而言,服务器瘫痪是一件很麻烦的事。


条款13 以对象管理资源

当我们想要管理资源时。如动态分配的内存,例如new *p,我们不但需要记得在程序结束时delete p还要保证在new与delete之间不会出现异常,也不会中途return。否则程序无法运行到delete那步。
让程序员时刻保持这种做法是十分困难的,更不用说当换了个人来继续push这个项目时,他可能并不完全理解你的思路,所以:

item13提到了用对象管理资源,即在初始化时获得资源(如动态分配指向某内存的指针),在析构时自动释放资源(归还内存)。

PS:析构仅代表该对象被删除,析构了,并不代表对象中的动态内存(如指针所指内容)被归还了。

例如文中提到的auto_ptr,析构时自动delete指针所指内容,虽然该智能指针现在已经不用了,但是它提供了两种管理对象的思路:

  • 建立RAII(Resource Acquisition Is Initialization)对象。这种观念常被称为:“以对象管理资源”或者“资源取得时机便是初始化时机”。
  • 管理对象运用析构函数确保资源被释放。如:
class A{public:    A(){ p=new int(1); }    ~A(){ delete p;}private:    int *p;};

常用典型RAII类shared_ptr


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

item13阐述的主要是动态资源的管理的一种观念,并将此观念作为内存管理的脊柱,如果我们这样设计类,就不用时时刻刻想着delete有没有完成了。

item14针对的更为具体,文章首先用mutex举例,在std::mutex中,它是不允许被复制的。再提交对于动态分配的内存如指针,如果指针所指向的内容没被复制,则当第一个RAII对象析构时,内存以被归还,复制的对象指向的内存将是未定义。

所以我们需要小心资源管理类的copying行为,有4种方法:

  • 禁止复制:将拷贝函数与复制运算符声明为私有(对于如Mutex)。
  • 对底层资源祭出“引用计数法”,如shared_ptr。
  • 复制底部资源,深度拷贝。
  • 转移底部资源的所有权。

条款15 在资源管理类中提供对原始资源的访问

item15首先讲述了为什么资源管理类要提供对于原始资源的访问,即其他函数(API)通常需要资源管理类提供原始数据进行操作。这样更方便。

第二,简要的说明了对原始资源的访问可能经由显示转换或隐式转换。一般而言显示转换比较安全,但隐式转换对客户比较方便


条款16 成对使用new和delete时要采取相同形式

item16非常简洁的阐述了new与delete配对用,new [] 与delete []配对用。

PS:new与delete的主要过程

  • new:分配内存,调用构造函数
  • delete:调用析构函数,归还内存

条款17 以独立语句将newed对象置于智能指针

item17:以独立语句将newed对象置入智能指针,在如下代码中

 func1(new int(),func2);

可能存在内存泄露。为什么呢?其执行过程如下

  • 分配内存
  • 执行func2/调用构造函数
  • 调用构造函数/执行func2

如果第二步是执行func2,并且抛出了异常,则分配内存后并没有调用构造函数。所以新建指针时使用独立语句是十分必要的。

原创粉丝点击