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

释放双眼,带上耳机,听听看~!

一.前言

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

二.先举个栗子

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

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

三.资源对象

        有了前面的解释,我们现在大概能够对为什么需要将资源当对象来看待有了理解。 下面我们来简单来介绍如何实现:

  • 先将资源封装成类,完成资源的初始化加载,和释放。

  • 现在我们可以用上面这个模板类来管理上面的指针。不过,上面的代码还没有完成。

  • 在资源管理中,有时候会出现这样的语句:

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

  • 1.如果是图片类的资源,在赋值的时候应该是资源的拷贝。

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

关于以上三种情况如何实现拷贝控制函数,我们留到下节继续介绍。

给TA打赏
共{{data.count}}人
人已打赏
安全技术

c++ list, vector, map, set 区别与用法比较

2022-1-11 12:36:11

安全经验

WildFly 18 的安全特性预览,将支持 TLS 1.3

2019-6-18 11:12:22

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索