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


    必须要注意的 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的时候释放资源。
    所以,以上不同的类型也决定着类中的拷贝控制函数。
    
    
    关于以上三种情况如何实现拷贝控制函数,我们留到下节继续介绍。

    https://blog.csdn.net/y1196645376/article/details/53005803

  • 相关阅读:
    swift5.x for-in, switch语句
    swift5.x 数组(Array)的基本操作
    OC NSDictionary的属性一般为什么要设置为copy
    iOS APP 从编译到运行
    重装win10系统之后,如何使用之前的虚拟机
    [Delphi]接口认识
    [QPlugins]学习大纲
    [QPlugins]概述
    [转发]Oauth 1.0 1.0a 和 2.0 的之间的区别有哪些?
    [Delphi] Webbroker ISAPI 示例说明
  • 原文地址:https://www.cnblogs.com/leijiangtao/p/12059848.html
Copyright © 2020-2023  润新知