美文网首页
关于ObjectC引用计数的粗糙解释

关于ObjectC引用计数的粗糙解释

作者: LikeSnooker | 来源:发表于2018-03-03 18:33 被阅读0次

引用计数,oc进行内存管理的一个技术。此计数记录了一个对象被指针指向的次数。提到指针,很多书籍都将指针比喻成牵牛的绳子。那oc种的牵牛绳牵的是一头很聪明的牛,当它察觉到自己身上不再有绳子牵着的时候就会跑掉,更神奇的是自个儿跑回牛棚里(对应的概念就是当引用计数为0的时候,内存被释放,释放的内存可被系统再分配)。

现在我们自己实现这一简单的功能,选择用c++的原因是,c++有操作符重载,以及析构函数。这对于我们要实现的简陋内存管理是非常方便的.

首先根类NSObject的代码如下:

class NSObject
{
public:
    int refereceCount_;
public:
    NSObject()
    {
        refereceCount_ = 0;
    }
    NSObject(int _ix)
    {
        refereceCount_ = 0;
    }
    NSObject(string name)
    {
        refereceCount_ = 0;
        name_          = name;
    }
    ~NSObject()
    {
        cout <<name_ <<"跑回牛棚" <<endl;
    }
public:
    string name_;
};

两个成员变量 refereceCount_ 和 name_,分别是引用计数和对象标识。引用计数存放在对象里的原因显而易见,因为这样只需保持一份,一处更改处处生效。如果存放在指针中,就存在更新引用计数要一同更新多个副本的问题。
指针类:

class Pointer
{
public:
    virtual Pointer& operator = (NSObject * pt) = 0;
    virtual ~Pointer()
    {
        
    }
};

指针类要实现两个功能,一是指向对象,二是指针相互赋值。这里就是重载了赋值操作符实现的。主要看看这个StrongPointer:

class StrongPointer:public Pointer
{
public:
    Pointer& operator = (NSObject * pt)
    {
        pt2Object_ = pt;
        if(pt != NULL)
            pt->refereceCount_ ++;
        cout << "强绳子套住 ("<<pt->name_<<") ,引用计数加1,此时的引用计数为 "<<pt2Object_->refereceCount_<<endl;
        return *this;
    }
    StrongPointer& operator = (const WeakPointer   & pointer)
    {
        if(pt2Object_!=NULL)
        {
            pt2Object_->refereceCount_ --;
            cout << "绳子将要被解除 ,(" <<pt2Object_->name_<<") 引用计数减1,此时的引用计数为 "<<pt2Object_->refereceCount_<<endl;
            if(pt2Object_->refereceCount_ == 0)
                delete pt2Object_;
        }
        pt2Object_ = pointer.pt2Object_;
        if(pt2Object_ != NULL)
            pt2Object_->refereceCount_ ++;
        
        cout << "强绳子套住 (" <<  pointer.pt2Object_->name_<<"),引用计数加1,此时的引用计数为 "<<pt2Object_->refereceCount_<<endl;
        return * this;
    }
    StrongPointer& operator = (const StrongPointer & pointer)
    {
        if(pt2Object_!=NULL)
        {
            pt2Object_->refereceCount_ --;
            cout << "绳子将要被解除 ,(" <<pt2Object_->name_<<") 引用计数减1,此时的引用计数为 "<<pt2Object_->refereceCount_<<endl;
            if(pt2Object_->refereceCount_ == 0)
                delete pt2Object_;
        }
        pt2Object_ = pointer.pt2Object_;
        if(pt2Object_ != NULL)
            pt2Object_->refereceCount_ ++;
        
        cout << "强绳子套住 (" <<  pointer.pt2Object_->name_<<"),引用计数加1,此时的引用计数为 "<<pt2Object_->refereceCount_<<endl;
        return *this;
    }
    StrongPointer()
    {
        pt2Object_ = NULL;
    }
    ~StrongPointer()
    {
        if(pt2Object_ ==NULL)
            return;
        pt2Object_->refereceCount_ --;
        
        if(pt2Object_->refereceCount_ == 0)
        {
            cout << "强绳子被解除, ("<<pt2Object_->name_<<") 引用计数减1,此时引用计数为0"<<endl;
            delete pt2Object_;
        }
        else
        {
            cout << "强绳子被解除, ("<<pt2Object_->name_<<") 引用计数减1,此时的引用计数为 "<<pt2Object_->refereceCount_ <<endl;
        }
    }
protected:
    NSObject * pt2Object_;
};

主要看以下两个函数
Pointer& operator = (NSObject * pt) 和 StrongPointer& operator = (const StrongPointer &pt) 分别接受对象(虽然这里实际上还是对象的指针,这个指针是c++概念里的指针,StrongPointer类的对象才是我们要表示这个牵牛绳的物件。)
和另一个指针类实体。 所做的事情也很简单 ,将所指向的对象的引用计数加一。_refereceCount设为公有是很不负责任的行为,但是为了方便,暂且就这么做了。

另外一个重要的点就是这个析构函数,当指针类自身被销毁的时候,也就是牵牛绳不在了的时候,牛是要记住自己身上的牵牛绳少了一根的,特别的,当牵牛绳统统都不见了,牛就跑回牛棚(内存被系统回收.)

测试看下结果:

StrongPointer  s_pt1 ;
    s_pt1                 = new NSObject("黄牛");
    
    StrongPointer * s_pt2 = new StrongPointer();
    *s_pt2                = new NSObject("黑牛");
1.jpeg

可以看到的是 我们找来了两个 “绳子” ,s_pt1,spt_2。这两个"绳子"分别来自栈和堆,当程序运行结束时 栈上的“绳子”就会被自动解除,于是它栓的牛也就跑了

看另外一段代码:

StrongPointer  s_pt1 ;
    s_pt1                 = new NSObject("黄牛");
    
    StrongPointer * s_pt2 = new StrongPointer();
    *s_pt2                = new NSObject("黑牛");
    
    *s_pt2                = s_pt1;
2.jpeg

同样还是两根绳子,原本是黄牛跑回了牛棚,这次我们将原本栓在黑牛身上的绳子拴在了黄牛身上,于是黑妞就当场跑了。黄牛身上有两个绳子,一个会自动销毁,一个不会,于是最后黄牛还是会被拴在原地。

相关文章

  • 关于ObjectC引用计数的粗糙解释

    引用计数,oc进行内存管理的一个技术。此计数记录了一个对象被指针指向的次数。提到指针,很多书籍都将指针比喻成牵牛的...

  • iOS retain,assign,strong,weak区别以

    MRC: ARC: copy与retain区别: 关于引用计数 生成对象并设置引用计数 = 1 : alloc...

  • OC高级编程之内存管理

    一、内存管理的思考方式下文会常用到的术语解释生成对象:创建对象持有对象:引用计数+1释放对象:引用计数-1废弃对象...

  • iOS内存管理初探 – 引用计数、AutoRelease与ARC

    引用计数式内存管理 引用计数 iOS通过引用计数管理对象的生命周期,每个对象有其引用计数。 对象被强引用时引用计数...

  • Obj-C高级编程--内存管理

    自动引用计数 自动引用计数:指内存管理中对引用采取自动计数的技术。 内存管理/引用计数 持有对象引起引用计数加...

  • iOS面试题:什么是arc?(arc是为了解决什么问题诞生的?)

    先解释ARC: automatic reference counting自动引用计数。 ARC几个要点: 在对象被...

  • GC算法

    引用计数 每个对象有一个引用计数,当对象被多引用一次,引用计数加一,当引用被释放,引用计数减一,当引用计数为零,则...

  • 循环引用

    循环引用解释:循环引用可以简单理解为A引用了B,而B又引用了A,双方都同时保持对方的一个引用,导致任何时候引用计数...

  • 内存管理与自动引用计数—第一日

    自动引用计数 1.1 什么是自动引用计数 内存管理中对引用采用自动计数的计数 1.2 内存管理/引用计数 这一张举...

  • 面试——关于引用计数

    强引用、弱引用 强引用影响对象的引用计数,进而影响对象的生存期。弱引用不影响对象的引用计数,在功能上类似于普通指针...

网友评论

      本文标题:关于ObjectC引用计数的粗糙解释

      本文链接:https://www.haomeiwen.com/subject/ialtfftx.html