<Effective C++> (Item 13-15): 以对象管理资源

在以前的C++用法中,new是非常常见的用来动态分配内存的方式,但是有new必须有delete,将内存还给系统,否则就会造成内存泄露,这是很危险的一件事情,而以对象管理资源这一思想就能比较好的解决这一问题

通常情况下,对于一个对象,如果是built-in类型,我们就直接new了,如果是自定义类型,一般使用工厂函数返回其指针,生成对象之后肯定需要释放对象吧,对于内置类型,就是成对的使用delete,但是程序复杂之后,这其实是很难做到的,对于自定义类型,一般的做法就是另定义一个函数,在这个”释放者函数”内delete相关资源,但是也很容易产生问题——如果在delete之前,函数就return了呢?或者就continue了呢?还是会内存泄漏。

把资源放进对象就可以很好的避免这个问题,封装入对象,在对象层面对其进行操作,则在资源需要释放的时候,就会自动调用析构函数,而不需要我们如履薄冰一般的手动delete了,这里还提到一种叫做RAII(Resource Acquisition is Initialization)的原则,即获得这个对象时立刻将其置入管理资源的类中。

C++11以前有一个auto_ptr指针,但是已经被弃用了所以不推荐,如果只打算一个指针管理一个对象,那么使用unique_ptr就行了,否则用 shared_ptr,要时刻注意的是,智能指针虽叫智能指针,其实质是一个模板类,如果要用智能指针重写之前的以指针传递的函数,则要使用.get()成员函数获得原始指针。

class Before{
...
private:
    type* item;
}
...
lock(type* item);

...
//用shared_ptr重写
class Before{
...
private:
    std::shared_ptr<type> item;
}
...
lock(type* item.get())

注意unique_ptr指针不能传递对象,即不能复制。

因此引出——在资源管理类中小心coping行为

如果是复制对于设计者来说是个敏感操作,那么首先可以考虑禁用复制构造函数/赋值操作符,使用之前说过的=delete方法,如果确实复制操作,则可以考虑使用shared_ptr的引用计数,只是要注意智能指针当引用计数为0的时候,调用删除器,对象是被销毁的,如果不希望对象是被销毁的操作,那么需要我们自行传递一个deleter,覆盖默认的删除器,可以参考另一篇博客,只是强调:
①:shared_ptr的传递删除器(deleter)方式比较简单, 只需要在参数中添加具体的删除器函数名, 即可; 注意是单参数函数;
②:unique_ptr的删除器是函数模板(function template), 所以需要在模板类型传递删除器的类型(即函数指针(function pointer)), 再在参数中添加具体删除器,博客:
智能指针自定义删除器

还有不能忽略的是,管理资源的类拷贝时,往往要复制最底层的资源,所以应该是深拷贝!!!!!!

在实际使用的过程中,虽然使用资源管理类封装了我们的对象,但是还是免不了要访问其原始资源,这就需要我们的资源管理类提供对原始资源的访问了。

就像前面说的,shared_ptr有一个get()成员函数,可以返回被管理对象的原始指针,除此之外,shared_ptrunique_ptr都重载了->*操作符,我们可以向使用普通的指针一样的操作被管理类而不用改变编码习惯,这也是标准库中这样的智能指针被称之为指针的原因吧,毕竟它们的使用非常接近传统的指针。

//最好使用make_shared函数初始化智能指针
std::shared_ptr<Type> i=std::make_shared<Type>(createInstance);
//可以像这样使用
...
i->memFunc();
...
(*i).getItem();

所以当我们设计自己的资源管理类而不是使用标准库版本的时候,我们也可以采用类似的做法,比如设计一个get()接口函数,返回我们的原始资源,当然如果你想要更省力的话,可以使用隐式转换函数,但是为了避免隐式转换的滥用,还是建议使用设计get()函数,显式转换更安全。

最后需要注意的是,同时也是OOP编程的原则之一——不要破坏封装性,不需要/不希望提供给类使用者的细节都应该隐藏起来,在这里需要访问/获得原始数据的部分,则通过接口函数提供给使用者。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值