• 全面推行使用智能指针的权利


    今天,我们讨论了使用的功能返回一个指向下一个潜在的错误。如果有一个函数返回一个指针MyClass对象的指针类型。

    MyClass* MyFactoryClass::Create(const Inputs& inputs);

    这个函数的一个非常显而易见的问题是。它的调用者是否负责删除这个对象?或者说这个指针所指向的MyClass类的实例是MyFactoryClass所拥有的实例?这个问题显然应该在声明这个函数的头文件里以凝视的形式说明。但在软件的世界里,实际上非常少可以做到这样。

    可是。即使函数的作者确实提供了一个凝视。表示这个函数在堆上创建了一个新对象,而且由它的调用者负责删除这个对象,我们将会发现自己面临这样一种处境:每当我们接到一个由函数调用所返回的指向某个对象的指针时,我们须要记得检查凝视(或者在没有凝视时,检查代码本身)来判断是否由我们负责删除这个对象。

    正如前面所说的,我们应该很多其它地依赖编译器而不是程序猿。因此。实行这个对象全部权的一种可靠方法是让函数返回一个智能指针。

    比如:

    RefCountPtr<MyClass> MyFactoryClass::Create(const Inputs& inputs);

    这样的设计使函数所返回的对象的全部权毫无争议,不会留下内存泄露的机会。还有一方面,假设认为引用计数指针速度过慢不适合须要,也能够返回一个作用域指针。但这样就产生了一个问题:ScopedPtr<MyClass> 无法被复制。因此不能依照传统方法返回:

    ScopedPtr<MyClass> MyFactoryClass::Create(const Inputs& inputs)
    {
    	ScopedPtr<MyClass> result(new MyClass(inputs));
    	return result; //无法通过编译
    }

    因此,解决问题的方法例如以下:

    ScopedPtr<MyClass> result;//创建一个空的作用域指针
           //填充它
    void MyFactoryClass::Create(const Inputs& inputs,ScopedPtr<MyClass>& result);

    我们创建一个包括NULL值的作用域指针。并让MyFactoryClass::Create()方法填充他。

    这种方法也不会使这个函数所创建的对象的全部权出现错误。假设不确定应该返回哪种指针,能够选择下列方案之中的一个:

    • 假设须要,返回速度更快的ScopedPtr。并使用它的Release()方法转移全部权。
    • 同一时候通过两种方法
    另一种相反的情况是,SomeClass::Find()方法返回一个指向一个对象的指针,但用户并不拥有这个对象的全部权:

    //返回一个指向一个结果的指针,调用者“并不拥有这个结果的全部权”
    MyClass* SomeClass::Find(const Inputs& inputs);

    这样的情况下,这个函数所返回的指针,指向属于SomeClass内部的某个对象的一个对象。

    对于上述第一个问题,SomeClass类觉得自己将负责删除它刚返回的那个指针所指向的MyClass实例。因此会在未来的某个时刻将它删除。

    在这样的情况下。假设这个函数的用户将删除他所接收到的指针。这个实例将被删除不止一次。这显然不是个好主意。其次,这个实例可能是一个vector模板中使用new[]操作符(带方括号)创建的一个MyClass对象数组的一部分,而如今我们将使用不带方括号的delete操作符从这个数组中删除一个对象。

    这相同不是个好的做法。最后,MyClass实例可能是在堆栈上创建的,根本不应该使用delete操作符进行删除。

    在这样的情况下,不论什么试图删除我们并不拥有的对象的行为(直接删除。或者把它赋值给一个将接收对象全部权的不论什么类型的智能指针)将会导致灾难。

    返回这样的指针的一种合适的方法是返回一个”半智能“指针,它并不拥有它所指向的对象的全部权。

    总结:为了避免内存泄露,建议遵从下面规则:

    • 每次使用new操作符创建一个对象时,马上把结果赋值给一个智能指针(推荐使用引用计数指针或作用域指针)
    • 使用new操作符时不要带方括号。假设创建一个数组,能够创建一个新的vector模板,它表示单个对象。
    • 避免循环引用
    • 在制备指针返回到功能时,它应该返回一个智能指针而不是原始指针,为了落实没事的结果。


  • 相关阅读:
    JS-Array数组对象
    JS-Math对象
    JS-Date对象
    JS-流程控制汇集
    css笔记
    CSS3-box盒布局
    css笔记
    CSS3中的animation动画
    JS-百钱买百鸡案例-for循环制作
    JS-用js的for循环实现九九乘法表以及其他算数题等
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5032483.html
Copyright © 2020-2023  润新知