必须要注意的 C++ 动态内存资源管理(一)——视资源为对象

一.前言

        所谓资源就是,一旦你用了它,将来必须还给系统。如果不这样,糟糕的事情就会发生。C++ 程序中最常见使用的资源就是动态分配内存(如果你分配了内存却忘记归还它,就会导致内存泄漏)。但是内存只是你必须管理的众多资源之一。其他常见的资源还有:文件描述器(file descriptors)互斥锁(mutex locks)、图形界面中的字体笔刷数据库连接、以及网络sockets。无论哪种资源,重要的是,如果你不再使用它时,必须将它还给系统。


二.先举个栗子

        假设我们在做一个RPG小游戏,主人公Player在游戏中获得不同buff从而更换不同的武器,假定这里我们的武器就只有三种:Fist(拳头),Knife(刀),Gun(抢)。
        然后这三种武器继承自 class Weapon 基类。
        那么我们可以使用一个工厂函数(factory function)来提供我们不同的武器: Weapon* createWeapon(…) ;
        当你程序如此设计的时候,那么你的工厂类就主要负责生产了,而createWeapon的调用端就要有责任对获取的武器资源进行释放。举例如下:


void changeWeapon(params)
{
    Weapon* oldWeapon = playerWeapon;
    playerWeapon = createWeapon(params);
    ...
        delete oldWeapon;
}
        以上代码看起来妥当,但在若干情况下,可能导致该函数释放oldWeapon——或许因为”…”中的某个过早的return语句。如果这样一个return语句被执行;又或者是因为”…”中有异常抛出;这些情况发生吃,那么控制流一定就不会触及到delete语句;而之前申请的内存(oldWeapon)就无可避免的泄露了。
        当然了,谨慎的编写程序可以防止这一类错误。但是有个问题是必须值得思考的,随着业务逻辑的更改,这段代码很可能会在时间渐渐过去之后被修改。一旦软件开始接受维护,很有可能会有某些人添加return语句或者continue语句而未能全然领悟它对函数资源管理策略造成的后果。
        这时候,我们需要将资源来视作一个对象来看。当构造初始化的时候获取资源,当析构销毁的时候释放资源。而析构函数是依赖C++的自动调用机制,这样我们就可以确保资源被释放。

                                                                          以对象管理资源                        ——————Effective C++ 条款13


三.资源对象

        有了前面的解释,我们现在大概能够对为什么需要将资源当对象来看待有了理解。 下面我们来简单来介绍如何实现:
  • 先将资源封装成类,完成资源的初始化加载,和释放。
template<typename T>
class res_ptr
{
public:
    typedef T _myType;
    typedef T* _myPType;
    res_ptr(_myPType p = nullptr) :pointer(p){  }
    ~res_ptr(){ delete pointer; }
private:
    _myPType pointer;
};
  • 现在我们可以用上面这个模板类来管理上面的指针。不过,上面的代码还没有完成。
  • 在资源管理中,有时候会出现这样的语句:
res_ptr<T>  p1;

...

res_ptr<T> p2 = p1;
  • 也就是赋值操作,在不同的场景中赋值操作可能有不同的含义(有时候不一定是赋值,可能是函数传参,函数返回)

    • 1.如果是图片类的资源,在赋值的时候应该是资源的拷贝。
    • 2.如果是文件、临接设备这样的资源,在赋值的时候应该是资源支配权的转移。
    • 3.如果是数据库连接,网络sokets这样的资源,在赋值的时候应该是增加资源的引用数,而当引用数为0的时候释放资源。
  • 所以,以上不同的类型也决定着类中的拷贝控制函数。


关于以上三种情况如何实现拷贝控制函数,我们留到下节继续介绍。
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值