Effective C++条款13:资源管理之(以对象管理资源)

一、资源释放失败的案例

  • 例如我们使用一个用来塑模投资行为(例如股票,债券等等)的程序库,其中各式各样的投资类型继承于一个基类Investment:
class Investment {};
  • 现在建立通过一个工厂函数供应我们获得某特定的Investment对象:
//返回一个Investment继承体系中的动态分配对象
Investment* createInvestment();
  • 如果我们在某作用域内调用这个函数返回的对象,那么使用完这个对象之后要复制删除这个对象
void f()
{
    Investment* pInv = createInvestment();
    //...
    delete pInv;
}

这种程序设计的缺陷

  • 缺陷主要在于我们可能无法释放获取的pInv对象:
    • 如果在delete之前有return语句导致函数执行结束,那么对象就无法释放
    • 如果在delete之前程序抛出异常,那么也无法释放对象
    • 如果这段代码在之后软件开发维护过程中被修改,那么后人可能无法知道要释放这个pInv对象,因为单纯的靠函数f中的delete语句来释放对象是行不通的

二、“以对象管理资源”的思想(RAII)

  • 对对象进行管理最好的方法就是让其自动申请资源和释放资源,这个时候我们会联想到构造函数(自动执行)和析构函数(自动执行)
  • 以对象管理资源的思想:
    • 获得资源后立刻放进管理对象内:获得资源之后将其封装到类中,例如shared_ptr等智能指针。实际上“以对象管理资源”的观念常被称为“资源获得时机便是初始化时机”(Resource Acquisition Is Initialization,RAII)
    • 管理对象运用析构函数确保资源被释放:当离开作用域之后,对象可以调用析构函数自动的释放资源,而无须我们手动释放。但是如果析构函数抛出异常,可能需要自己手动处理(析构函数异常处理可以参阅条款8)
  • C++程序库提供了两种类,更加安全的管理自己的资源,分别是:

三、auto_ptr

  • auto_ptr是个智能指针,其析构函数自动对其所指对象调用delete
  • 例如我们修改函数f,并利用auto_ptr获得对象,在函数作用域结束之后,资源自动释放
void f()
{
    //调用函数获得对象
    std::auto_ptr<Investment> pInv(createInvestment());


}//函数执行完之后,auot_ptr的析构函数自动删除pInv
  • auto_ptr对象的唯一性:auto_ptr只保存自己管理对象的一份副本,因此当auto_ptr被赋值或复制时,就会将自己的资源管理权转交给它人,从而是自己变为null
//获得一个对象,并管理该对象
std::auto_ptr<Investment> pInv1(createInvestment());

//拷贝pInv1,此时pInv1被设为null,现在pInv2管理这个资源
std::auto_ptr<Investment> pInv2(pInv1);

//赋值操作,此时pInv2变为null,现在pInv1管理这个资源
pInv1 = pInv2;

四、shared_ptr

五、没有针对“动态分配数组”而设计的智能指针

  • 注意:auto_ptr和shared_ptr析构函数中做释放资源使用的是delete而不是delete [],因此将动态数组绑定于智能指针对象上是不行的,但是数组是可以与智能指针使用的,详情可以参阅:https://blog.csdn.net/qq_41453285/article/details/95655647
  • 例如下面的操作都是错误的
//都是错误的
std::auto_ptr<std::string> aps(new std::string[10]);
std::shared_ptr<int> aps(new int[1024]);
  • C++没有为动态分配数组而设计的智能指针类,是因为C++已经有了vector和string这样的管理类,这些类已经够我们使用了,因此提供动态分配数组管理的类是多余的
  • 但是Boost库中的boost::scoped_array和boost::shared_array类是接近于为数组而设计的类,因此你们想要了解的话,可以参阅这两个类

六、总结

  • 为防止资源泄漏,请使用RAII对象,它们在构造函数中获得资源并在析构函数中释放资源
  • 两个常被使用的RAII类分别是tr1::shared_ptr和auto_ptr(以抛弃不再使用)
    • shared_ptr:前者通常是较佳选择,因为其拷贝行为比较直观
    • auto_ptr:复制动作会使它(被复制对象)指向null
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

董哥的黑板报

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值