精华内容
下载资源
问答
  • 引用计数法的循环引用问题
    2021-03-15 15:26:03

    关于引用计数法,我们可以先看一段wiki上的描述:

    As a collection algorithm, reference counting tracks, for each object, a count of the number of references to it held by other objects. If an object's reference count reaches zero, the object has become inaccessible, and can be destroyed.

    When an object is destroyed, any objects referenced by that object also have their reference counts decreased.

    作为一种回收算法,引用计数法记录着每一个对象被其它对象所持有的引用数。如果一个对象的引用计数为零,那么该对象就变成了所谓的不可达对象,亦即可以被回收的。

    当一个对象被回收后,被该对象所引用的其它对象的引用计数都应该相应减少。

    而所谓的循环引用(circular referrence)有是什么意思呢?举个简单的例子:public class MyObject {

    public Object ref = null;

    public static void main(String[] args) {

    MyObject myObject1 = new MyObject();

    MyObject myObject2 = new MyObject();

    myObject1.ref = myObject2;

    myObject2.ref = myObject1;

    myObject1 = null;

    myObject2 = null;

    }

    }

    从上面的代码可以轻易地发现myObject1与myObject2互为引用,我们知道如果采用引用计数法,myObject1和myObject2将不能被回收,因为他们的引用计数无法为零。aa601d322feaaba1ce7bb2eaa90203a4.png

    但是具体是为什么呢?已上图为例,当代码执行完line7时,两个对象的引用计数均为2。此时将myObject1和myObject2分别置为null,以前一个对象为例,它的引用计数将减1。若要满足垃圾回收的条件,需要清除myObject2中的ref这个引用,而要清除掉这个引用的前提条件是myObject2引用的对象被回收,可是该对象的引用计数也为1,因为myObject1.ref指向了它。以此类推,也就进入一种死循环的状态。

    更多相关内容
  • 本文实例讲述了Python引用计数操作。分享给大家供大家参考,具体如下: 为了简化内存管理,Python通过引用计数机制实现了自动的垃圾回收功能,Python中的每个对象都有一个引用计数,用来计数该对象在不同场所分别被...
  • 该demo主要展现智能指针和引用计数的实现过程,总共两个类,一个智能指针类,一个引用计数类,另外附一份执行步骤资料
  • 本篇文章是对PHP中的引用计数机制进行了详细的分析介绍,需要的朋友参考下
  • 给易语言的类使用引用计数。 继承object类之后, a=b 赋值的的时候 a和b指向同一个对象。 可以在方法返回自身,达到连续调用类的方法修改同一个对象的目的。
  •  一、模块使用计数的背景知识  模块是一种可以在内核运行过程中动态加载、卸载的内核功能组件。2.6内核中模块的命名方式为*.ko。模块在被使用时,是不允许被卸载的。编程时需要用“使用计数”来描述模块是否在被...
  • 主要介绍了 PHP7 中全新的 zval 容器和引用计数机制的相关知识, 主要侧重于解释新 zval 容器中的引用计数机制。需要的朋友可以参考下
  • c++实现引用计数

    2021-11-11 20:00:33
    下面是一个引用计数的一种实现。 示例 直接上代码,总共分为三部分,第一部分是基本类的定义,第二部分是对于基本类的使用类,第三部分是实现真正的引用计数功能。 // ReferenceCount.cpp : 定义控制台应用程序的...

    概述

    当有指针指向同一块内存空间时,计数器加1,没增加一个指向该内存空间的指针,计数器加1,同理,当原本指向该内存空间的指针指向另一块内存,计数器减1,被指向的另一个内存的计数器加1。下面是一个引用计数的一种实现。

    示例

    直接上代码,总共分为三部分,第一部分是基本类的定义,第二部分是对于基本类的使用类,第三部分是实现真正的引用计数功能。

    // ReferenceCount.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    #include <iostream>
    
    using namespace std;
    
    //基础对象类
    class MyPoint
    {
    public:
        MyPoint(int a = 0,int b = 0):x(a),y(b)
        {
    
        }
        void setPoint(int a,int b){x = a;y = b;}
        int getX() const {return x;}
        int getY()const {return y;}
    private:
        int x;
        int y;
    };
    
    //辅助类(共享资源,含有计数和共享的数据资源)
    class SharePoint
    {
        friend class SmartPtr;//友元函数可以访问类中的私有成员变量
        SharePoint(MyPoint *p):ptr(p),count(0){}
        ~SharePoint()
        {
            if(count == 0)
            {
                delete ptr;
            }
        }
        
        MyPoint *ptr;//共享的数据资源
        int count;//计数
    public:
        int getCount()const{return count;}
    };
    
    //智能指针类
    class SmartPtr
    {
    public:
        SmartPtr(MyPoint *p):ptr(new SharePoint(p))
        {
            ++ptr->count;
        }
        SmartPtr(const SmartPtr &p)//拷贝构造函数
        {
            ptr = p.ptr;
            ++ptr->count;
        }
        SmartPtr & operator=(const SmartPtr &p)//赋值运算符重载
        {
            if(this->ptr != p.ptr)
            {
                if(--ptr->count == 0)//原来指向的内存空间的计数减1
                {
                    delete ptr;
                }
                
                this->ptr = p.ptr;
                ++p.ptr->count;//新指向的内存空间的计数增加1
            }
            return *this;
        }
    
        SharePoint &operator*()
        {
            return *ptr;
        }
        SharePoint * operator->()
        {
            return ptr;
        }
    
    
        ~SmartPtr()
        {
            if(ptr->count == 0)
            {
                delete ptr;
            }
            else
            {
                --ptr->count;
            }
            cout<<"引用计数:"<<ptr->count<<endl;
        }
    
        SharePoint *getSourcePtr(){return ptr;}
    private:
        SharePoint *ptr;
    };
    
    //测试引用计数,可以看出引用计数的计数增加于减少
    void testReference()
    {
        MyPoint p(1,2);
        SmartPtr s1(&p);
        cout<<"引用计数的个数:"<<s1.getSourcePtr()->getCount()<<endl;
        {
            SmartPtr s2(s1);
            cout<<"引用计数的个数:"<<s1.getSourcePtr()->getCount()<<endl;
            {
                SmartPtr s3 = s2;
                cout<<"引用计数的个数:"<<s1.getSourcePtr()->getCount()<<endl;
            }
        }
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        //以下只能增加引用计数
        //MyPoint p(1,2);
        //SmartPtr s1(&p);
        //cout<<"引用计数的个数:"<<s1.getSourcePtr()->getCount()<<endl;
        //SmartPtr s2(s1);
        //cout<<"引用计数的个数:"<<s1.getSourcePtr()->getCount()<<endl;
        //SmartPtr s3 = s2;
        //cout<<"引用计数的个数:"<<s1.getSourcePtr()->getCount()<<endl;
        testReference();
    
        system("pause");
    	return 0;
    }
    
    

    以上代码是在vs2010上实现的,创建的环境是控制台程序,自动生成的项目结构如下:
    在这里插入图片描述
    以上仅供参考。

    展开全文
  • c++性能优化:引用计数

    千次阅读 2022-03-02 23:10:38
    引用计数 和自然界一样,玻尔兹曼熵法同样适用于代码世界。小型的软件在面对的用户不断增加的新功能就会需要不断迭代。这样的迭代就会带来代码的混乱,评断代码的混乱标准是衰变率。 与混乱的软件有关的主要难题就是...

    引用计数

    和自然界一样,玻尔兹曼熵法同样适用于代码世界。小型的软件在面对的用户不断增加的新功能就会需要不断迭代。这样的迭代就会带来代码的混乱,评断代码的混乱标准是衰变率。
    与混乱的软件有关的主要难题就是代码的内存讹误,也就是会发生代码的内存泄漏,指针的过早删除等等。但是在c++中使用一种机制来尽可能的避免使用指针带来的以上问题,它就是引用计数。引用计数的基本思想就是将指针的控制从客户放到对象本身,当没有对象使用这个指针的时候就把这个指针删除。
    引用计数有时还会被说成是一种性能优化,我们来看一下一个对象在复制或者赋值的时候发生了什么?

    class MyString {
    public:
        ...
        MyString& operator=(const MyString& chs);
        ...
    private:
        char* pdata;
    };
    
    MyString& MyString::operator=(const MyString& chs)
    {
        if (&chs == this) {
            return *this;
        }
        delete[] pdata;
        int length = strlen(rhs.pdata + 1);
        pdata = new char[length];
        mempy(pdata, chs.pdata, length);
    }
    
    MyString p,s;
    p = s = "TWO";  // 赋值
    

    这样的话在内存中就会存在两个TWO的内存,比较浪费空间。如果使用引用计数的话,可以将多个指针只想同一份资源,这样的话比较节省资源。

    实现细节

    我们以<<More Effective C++>>的Widget类为例来实现一个引用计数的类:

    class Widget {
    public:
        Widget();
        Widget(int size);
        Widget(const Widget& wgd);
        ~Widget();
    
        Widget& operator=(const Widget& Wdg);
        void doThis();
        int showThat() const;
    private:
        char* somePtr;
        int refCount; // 添加的引用计数
    };
    

    RCWidget是一个代理类,用于调用Widget

    class RCWidget{
    public:
        RCWidget(int size) : value(new Widget(size)) {}
        void doThis() { value->doThis(); }
        int showThat() { return value->showThat();}
    private:
        Widget* value;
    };
    

    上面的还只是简单的描述了Widget和其代理实现的过程。如果还需要真正实现引用计数的话还需要一个基类去继承(当然也可以直接在内部实现,这是这样扩展性比较好),如下图:
    在这里插入图片描述
    实现引用计数还是使用BigInt类比较合适,BigInt类是使用二进制编码的十进制数来表示正整数。例如:数字123内部有一个三字节的字符数组表示,每个字节代表一个数字。BigInt类使用的也是基类继承引用计数类的方式实现的:

    // c++性能优化:引用计数 BigInt
    class BigInt
    {
    friend BigInt operator+(const BigInt&, const BigInt&);
    
    public:
        BigInt(const char*);
        BigInt(unsigned int);
        BigInt(const BigInt&);
        BigInt& operator=(const BigInt&);
        BigInt& operator+=(const BigInt&);
        ~BigInt();
    
        char* getDigits() const { return digits; }
        unsigned int getNdigits() const { return ndigits; }
    private:
        char* digits;
        unsigned int ndigits;
        unsigned int size;
        BigInt(const BigInt&, const BigInt&);
        char fetch(unsigned int i) const;
    };
    
    // 构造
    BigInt::BigInt(unsigned int u)
    {
        unsigned int v = u;
        for (ndigits = 1; (v /= 10) > 0; ++ndigits) {
            ;
        }
    
        digits = new char[size = ndigits];
        for (unsigned int i= 0; i < ndigits; i++) {
            digits[i] = u % 10;
            u /= 10;
        }
    }
    
    BigInt::BigInt(const char* s)
    {
        if (s[0] == '\0') {
            s = "0";
        }
        size = ndigits = strlen(s);
        for (int i = 0; i < ndigits; i++) {
            digits[i] = 0;
        }
    }
    
    BigInt::BigInt(const BigInt& bigInt)
    {
        size = ndigits = bigInt.ndigits;
        digits = new char[size];
        for (int i = 0; i < ndigits; i++) {
            digits[i] = bigInt.digits[i];
        }
    }
    
    BigInt::BigInt(const BigInt& left, const BigInt& right)
    {
        size = 1 + (left.ndigits > right.ndigits ? left.ndigits : right.ndigits);
        digits = new char[size];
        ndigits = left.ndigits;
        for (int i = 0; i < ndigits; i++) {
            digits[i] = left.digits[i];
        }
        *this += right;
    }
    
    char BigInt::fetch(unsigned int i) const
    {
        return 1 < ndigits ? digits[i] : 0;
    }
    
    BigInt& BigInt::operator+=(const BigInt& rhs)
    {
        unsigned int max = 1 + (rhs.ndigits > ndigits ? rhs.ndigits : ndigits);
        if (size < max) {
            char* d = new char[max];
            for (int k = 0; k < ndigits; k++) {
                d[k] = digits[k];
            }
            delete [] digits;
            digits = d;
        }
    
        while (ndigits < max)
        {
            digits[ndigits++] = 0;
        }
    
        for (int i = 0; i < ndigits; i++) {
            digits[i] += rhs.fetch(i);
            if (digits[i] >= 10) {
                digits[i] -= 10;
                digits[i + 1] += 1;
            }
        }
        if (digits[ndigits - 1] == 0) {
            --ndigits;
        }
        return *this;
    }
    
    BigInt operator+(const BigInt& left, const BigInt& right)
    {
        return BigInt(left, right);
    }
    
    // 析构
    BigInt::~BigInt() {
        delete [] digits;
    }
    
    // 赋值
    BigInt& BigInt::operator=(const BigInt& rhs)
    {
        if (this == &rhs) {
            return *this;
        }
        if (ndigits > size) {
            delete [] digits;
            digits = new char[size = ndigits];
        }
        for (unsigned int i = 0; i < ndigits; i++) {
            digits[i] = rhs.digits[i];
        }
    
        return *this;
    }
    
    // RCObject 用于引用计数的基类,封装的引用计数变量和有关的操作
    class RCObject
    {
    public:
        void addRef() { ++refCount; }
        void removeRef() { if(--refCount == 0) delete this;}
        void markUnshareable() {shareable = false;}
        bool isShareable() const {return shareable;}
        bool isShared() const { return refCount > 1;}
    
    protected:
        RCObject() : refCount(0), shareable(true) {}
        RCObject(const RCObject& rhs) : refCount(0), shareable(true) {}
        RCObject& operator=(const RCObject& rhs) {return *this;}
        virtual ~RCObject() {}
    
    private:
        unsigned int refCount;
        bool shareable;
    };
    
    // 修改BigInt,继承RECObject,内部实现不用变化
    // class BigInt : public RCObject
    // {
    
    // };
    
    // 使用智能指针类指向指向BigInt对象,实现真正的引用计数,下面是智能指针的简单实现
    template<class T>
    class RCPtr
    {
    public:
        RCPtr(T* realPtr = 0) : pointee(realPtr) {init();}
        RCPtr(const RCPtr& rhs) : pointee(rhs.pointee) {init();}
        ~RCPtr() { if(pointee) pointee->removeRef();}
        RCPtr& operator=(const RCPtr& rhs);
        T* operator->() const {return pointee;}
        T& operator*() const {return *pointee;}
    private:
        T* pointee;
        void init();
    };
    
    template<class T>
    void RCPtr<T>::init()
    {
        if (0 == pointee) return;
        if (false == pointee->isShareable()) {
            pointee = new T(*pointee);
        }
        pointee->addRef();
    }
    
    template<class T>
    RCPtr<T>& RCPtr<T>::operator=(const RCPtr& rhs)
    {
        if (pointee != rhs.pointee) {
            if (pointee) pointee->removeRef();
            pointee = rhs.pointee;
            init();
        }
        return *this;
    }
    
    // 最后的引用计数类RCBigInt
    class RCBigInt
    {
    friend RCBigInt operator+(const RCBigInt&, const RCBigInt&);
    public:
        RCBigInt(const char* p) : value(new BigInt(p)){};
        RCBigInt(unsigned int u = 0) : value(new BigInt(u)){};
        RCBigInt(const BigInt& bi) : value(new BigInt(bi)){};
        void print() const {value->print();}
    private:
        RCPtr<BigInt> value;
    };
    
    inline
    RCBigInt RCBigInt::operator+(const RCBigInt& left, const RCBigInt& right)
    {
        return RCBigInt(*(left.value), *(right.value));
    }
    

    后面还是用具体的方法来测试这个结果:

    // 测试函数
    void testBigIntCreate(int n)
    {
        GetSystemTime(&t1); // 计算时间,具体实现未写明
        for (int i = 0; i < n; i++) {
            BigInt a = i;
            BigInt b = i + 1;
            BigInt c = i + 2;
        }
        GetSystemTime(&t2);
    }
    
    void testRCBigIntCreate(int n)
    {
        GetSystemTime(&t1); // 计算时间,具体实现未写明
        for (int i = 0; i < n; i++) {
            RCBigInt a = i;
            RCBigInt b = i + 1;
            RCBigInt c = i + 2;
        }
        GetSystemTime(&t2);
    }
    
    void testBigIntAssign(int n)
    {
        BigInt a,b,c;
        BigInt d = 1;
        
        GetSystemTime(&t1); // 计算时间,具体实现未写明
        for (int i = 0; i < n; i++) {
            a = b = c = d;
        }
    
        GetSystemTime(&t2);
    }
    

    以上结果可以得知,使用了引用计数的RCBigInt要比正常的BigInt高效的多,基本是成倍的增长。
    因此可以看出引用计数对于性能有时候是有较大的增益的。但是也需要具体区分引用计数和执行速度的关系。比如说比较极端的情况,多数的目标对象但是对应的引用计数很少,也就是创建出来之后很少被引用,这样的话资源的创建和消耗并不会优化很多。

    已存在类

    对于某些库无法修改其源代码的时候,我们只能够另外寻找方法实现,比较好的方法就是单独引入一个类计数Countholder。同时,之前代理类中的智能指针也会修改到Countholder中来间接指向BigInt。但是这样的话我们也可以预想到他的执行效率会比较低,因为还需要创建单独的Countholder。
    在这里插入图片描述
    代码如下:

    // 首先,BigInt不继承RCObject,添加PCIPtr指向CountHolder
    template<class T>
    class PCIPtr
    {
    public:
        PCIPtr(T* realPtr = 0);
        PCIPtr(const PCIPtr& rhs);
        ~PCIPtr();
    
        PCIPtr& operator=(const PCIPtr& rhs);
        T* operator->() const {return counter->pointee;}
        T& operator*() const {return *(counter->pointee);}
    private:
        struct CountHolder : public RCObject {
            ~CountHolder() {delete pointee;}
            T* pointee;
        };
        PCIPtr<T>::CountHolder *counter;
        void init();
    };
    
    template<class T>
    void PCIPtr<T>::init()
    {
        if (0 == counter) return;
    
        if (false == counter->isShareable()) {
            counter = new CountHolder();
            counter->pointee = new T(*counter->pointee);
        }
        counter->addRef();
    }
    
    template<class T>
    PCIPtr<T>::PCIPtr(const PCIPtr& rhs)
        : counter(rhs.counter)
    {
        init();
    }
    
    template<class T>
    PCIPtr<T>::~PCIPtr()
    {
        if (counter) {
            counter->removeRef();
        }
    }
    
    template<class T>
    PCIPtr<T>::operator=(const PCIPtr& rhs)
    {
        if (counter != rhs.counter) {
            if (counter) counter->removeRef();
            counter = rhs.counter;
            init();
        }
        return *this;
    }
    

    并发引用计数

    多线程环境下的引用计数,这种情况下引用计数的操作需要受到锁的保护。这样的话RCBigInt类就需要修改,我们修改的是RCIPtr的定义,加上了MutexLock的模板参数,并且修改了RCIPtr类。
    RCIPtr修改后:

    template<class T, class LOCK>
    class PCIPtr
    {
    	...
    private:
        struct CountHolder : public RCObject {
            ~CountHolder() {delete pointee;}
            T* pointee;
            LOCK key;
        };
        PCIPtr<T, LOCK>::CountHolder* counter;
        void init();
    };
    
    // init方法不受影响,但是在访问的时候需要加上原子操作
    template<class T, class LOCK>
    void PCIPtr<T,LOCK>::init()
    {
        if (0 == counter) return;
    
        if (false == counter->isShareable()) {
            counter = new CountHolder();
            counter->pointee = new T(*counter->pointee);
        }
        counter->addRef();
    }
    
    template<class T, class LOCK>
    PCIPtr<T,LOCK>::PCIPtr(T* realPtr)
        : counter(new CountHolder)
    {
        counter->pointee = realPtr;
        init();
    }
    
    template<class T, class LOCK>
    PCIPtr<T,LOCK>::PCIPtr(const PCIPtr& rhs)
        : counter(rhs.counter)
    {
        if (rhs.counter) rhs.counter->key.lock();
        init();
        if (rhs.counter) rhs.counter->key.unlock();
    }
    
    template<class T, class LOCK>
    PCIPtr<T,LOCK>::~PCIPtr()
    {
        if (counter) {
            counter.key->lock();
            counter->removeRef();
            counter.key->unlock();
        }
    }
    
    template<class T, class LOCK>
    PCIPtr<T,LOCK>::operator=(const PCIPtr& rhs)
    {
        if (counter != rhs.counter) {
            if (counter) {
    			counter.key->lock();
    			counter->removeRef();
    			counter.key->unlock();
    		}
            counter = rhs.counter;
        	if (rhs.counter) rhs.counter->key.lock();
        	init();
        	if (rhs.counter) rhs.counter->key.unlock();
        }
        return *this;
    }
    

    由于增加了lock相关的实现,在性能上会增加一定的消耗,但是还是可以比正常的BigInt要节省时间。

    要点

    引用计数和执行速度、资源节约之间有着一种微妙的相互关系,需要满足一些条件才有可能是的引用计数有利资源节约。这些条件是:目标对象消耗大量的资源、资源的分配和释放很昂贵、高度共享:由于赋值和复制函数,是的引用计数比较大;引用的创建和清除比较廉价。

    展开全文
  • MyString 字符串类仿写_C++_(四种版本,引用计数,迭代器,加锁)
  • 深入Python中引用计数

    2020-12-24 16:30:36
    在python中的垃圾回收机制主要是以引用计数为主要手段以标记清除和隔代回收机制为辅的手段 。可以对内存中无效数据的自动管理!在这篇文章,带着这个问题来一直往下看:怎么知道一个对象能不能被调用了呢?回顾内存...

    在python中的垃圾回收机制主要是以引用计数为主要手段以标记清除和隔代回收机制为辅的手段 。可以对内存中无效数据的自动管理!在这篇文章,带着这个问题来一直往下看:怎么知道一个对象能不能被调用了呢?

    回顾内存地址

    Python中的任何变量都有对应的内存引用,也就是内存地址。

    如果不是容器类型,那么直接引用和赋值,内存地址都是不会的。

    >>> a = 1

    >>> b = 1

    >>> id(a)

    140709385600544

    >>> id(b)

    140709385600544

    如果在内存中创建了一个list对象(容器),而且对该对象进行了引用。那么b = [1,2]和c = a有什么区别?

    >>> a = [1,2]

    >>> b = [1,2]

    >>> id(a)

    1966828025736

    >>> id(b)

    1966828044488

    >>> c = a

    >>> id(c)

    1966828025736

    首先在内存1966828025736处创建了一个列表 [1,2],然后定义了一个名为a的变量。b = [1,2]会新开一个内存地址,c = a直接赋值直接引用[1,2]的内存地址。

    引用计数

    在一些代码中,如果存在一些变量但是没有用,会造成内存空间,因此叫做垃圾,所以要回收。

    引用计数也是一种最直观,最简单的垃圾收集技术。原理非常简单,每一个对象都包含了两个头部信息,一个是类型标志符,标识这个对象的类型;另一个是计数器,记录当前指向该对象的引用数目,表示这个对象被多少个变量名所引用。

    CPython 使用引用计数来管理内存,所有 Python 脚本中创建的实例,都会有一个引用计数,来记录有多少个指针指向它。当引用计数只有 0 时,则会自动释放内存。

    在Python中通过sys.getrefcount查看引用计数的方法,

    print(sys.getrefcount())

    注意调用getrefcount()函数会临时增加一次引用计数,得到的结果比预期的多一次。

    比如,下面这个例子中,a 的引用计数是 3,因为有 a、b 和作为参数传递的 getrefcount 这三个地方,都引用了一个空列表。

    >>> import sys

    >>> a = []

    >>> b = a

    >>> print(sys.getrefcount(a))

    3

    我们通过一些例子来看下,可以使python对象的引用计数增加或减少的场景。

    import sys

    a = []

    # 两次引用,一次来自 a,一次来自 getrefcount

    print(sys.getrefcount(a))

    def func(a):

    # 四次引用,a,python 的函数调用栈,函数参数,和 getrefcount

    print(sys.getrefcount(a))

    func(a)

    # 两次引用,一次来自 a,一次来自 getrefcount,函数 func 调用已经不存在

    print(sys.getrefcount(a))

    ########## 输出 ##########

    2

    4

    2

    引用计数是用来记录对象被引用的次数,每当对象被创建或者被引用时将该对象的引用次数加一,当对象的引用被销毁时该对象的引用次数减一,当对象的引用次数减到零时说明程序中已经没有任何对象持有该对象的引用,换言之就是在以后的程序运行中不会再次使用到该对象了,那么其所占用的空间也就可以被释放了了。

    计数增加和减少

    下面引用计数增加的场景:

    对象被创建并赋值给某个变量,比如:a = 'ABC'

    变量间的相互引用(相当于变量指向了同一个对象),比如:b=a

    变量作为参数传到函数中。比如:ref_method(a),

    将对象放到某个容器对象中(列表、元组、字典)。比如:c = [1, a, 'abc']

    引用计数减少的场景:

    当一个变量离开了作用域,比如:函数执行完成时,执行方法前后的引用计数保持不变,这就是因为方法执行完后,对象的引用计数也会减少,如果在方法内打印,则能看到引用计数增加的效果。

    对象的引用变量被销毁时,比如del a或者del b。注意如果del a,再去获取a的引用计数会直接报错。

    对象被从容器对象中移除,比如:c.remove(a)

    直接将整个容器销毁,比如:del c

    对象的引用被赋值给其他对象,相当于变量不指向之前的对象,而是指向了一个新的对象,这种情况,引用计数肯定会发生改变。(排除两个对象默认引用计一致的场景)。

    import sys

    def ref_method(str):

    print(sys.getrefcount(str))

    print("我调用了{}".format(str))

    print('方法执行完了')

    def ref_count():

    # 引用计数增加的场景

    print('测试引用计数增加')

    a = 'A'

    print(sys.getrefcount(a))

    b = a

    print(sys.getrefcount(a))

    ref_method(a)

    print(sys.getrefcount(a))

    c = [1, a, 'abc']

    print(sys.getrefcount(a))

    # 引用计数减少的场景

    print('测试引用计数减少')

    del b

    print(sys.getrefcount(a))

    c.remove(a)

    print(sys.getrefcount(a))

    del c

    print(sys.getrefcount(a))

    a = 783

    print(sys.getrefcount(a))

    if __name__ == '__main__':

    ref_count()

    ########## 输出 ##########

    测试引用计数增加

    78   #77+1 77在函数中是随机的

    79

    81

    我调用了A

    方法执行完了

    79

    80

    测试引用计数减少

    79

    78

    78

    4

    本文已收录 GitHub,传送门~[2] ,里面更有大厂面试完整考点,欢迎 Star。

    【编辑推荐】

    【责任编辑:姜华 TEL:(010)68476606】

    点赞 0

    展开全文
  • 本文分享Unity中的资源管理-引用计数 在前面的文章中, 我们一起学习了对象池的基本原理和几种实现, 今天和大家继续聊聊另一个资源管理中比较重要的技术: 引用计数. GC的基础知识 GC(Garbage Collection)是一种用来...
  • python引用计数的原理

    2022-01-20 23:44:39
    python的垃圾回收采用的是 引用计数机制为主和 分代回收机制为辅的 结合机制,当对象的引用计数变为0时,对象将被销毁,除了解释器默认创建的对象外(默认对象的引用计数永远不会变成0) python关于对象的管理:最...
  • GC-引用计数

    千次阅读 2019-04-08 21:16:19
    GC-引用计数法 GC:释放怎么都无法被引用的对象的机制。 引用计数法在对象的元数据区,加入了计数器,用于表示当前对象被引用了多少次。 引用计数法与其他GC算法相比,在于GC的的调用时机:GC标记-清除算法是在没有...
  • 相对于Java和Go,python的GC机制是相对简约的,其中最基础的机制之一就是引用计数。当对象生成时引用计数为1;对象被其它对象引用时引用计数增加1;对象没有被引用,又退出作用域的话,引用计数归0;引用计数归0后,...
  • 1.引用计数的思考方式 自己生成的对象,自己持有 非自己生成的对象,自己也能持有 不在需要自己持有的对象时释放 非自己持有的对象无法释放 2.引用计数的实现 1.alloc方法 + alloc + allocWithZone: class_...
  • NULL 博文链接:https://handy-wang.iteye.com/blog/1748158
  • netty引用计数机制

    2020-01-15 15:22:52
    如果应用需要一个资源,可以从netty自己的对象池中获取,新获取的资源对象的引用计数被初始化为1,可以通过资源对象的retain方法增加引用计数,当引用计数为0的时候该资源对象拥有的资源将会被回收。 这种方式相比于...
  • 引用计数算法

    千次阅读 2019-08-22 16:18:03
    相比于前面三种垃圾收集算法,引用计数算法算是实现最简单的了,它只需要一个简单的递归即可实现。现代编程语言比如Lisp,Python,Ruby等的垃圾收集算法采用的就是引用计数算法。现在就让我们来看下引用计数算法...
  • 例如,如果您有一个循环引用,则对象的引用计数永远不会减少为零,因此永远不会被删除。 但是对它们的所有引用都可能已经存在,因此无法以通常的方式获取它们的引用计数信息。 请注意,这两个函数都非常危险——...
  • OC 中的自动引用计数 ARC

    千次阅读 2022-03-31 10:18:49
    Automatic Reference Counting ,自动引用计数,ARC 系统自动的帮我们计算对象的引用计数器的值 2、ARC 的基本原则 ARC 是编译器机制。在编译器编译代码的时候,会在合适的位置插入 retain、release、autorelease ...
  • 引用计数的获取 因为对象的引用计数主要存储在isa位域extra_rc和散列表中,所以要获取对象的引用计数也需要从两个位置进行获取. uintptr_t _objc_rootRetainCount(id obj) { assert(obj); return obj->...
  • 我们需要确定一个节点是否需要销毁,是通过引用计数是否为零来判断的,很多语言使用的内存回收机制就是引用计数。 如果只标记当前节点和其一层依赖项,当其依赖项也作为主加载节点,我就没办法判断二层依赖节点是否...
  • AVFrame 引用计数 测试代码 Test_AVFrame.cpp #include <iostream> using namespace std; extern "C" // 指定函数是 C 语言函数,函数目标名不包含重载标识,C++ 中调用 C 函数需要使用 extern "C" ...
  • 自动引用计数是在Objective-C中就有的特性,用来辅助管理对象的引用,这里我们就来以实例讲解Swift中引用类型的ARC自动引用计数:
  • 介绍了Java中的垃圾分析算法,包括引用计数法和可达性分析算法的原理!
  • 今天和人争论C++ 智能指针shared_ptr引用计数问题,然后代码实现验证,这里分享给大家。 一、C++ 智能指针shared_ptr shared_ptr智能指针是一个类,用于管理new 分配的对象,该智能指针类内部有一个保存引用计数的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 262,131
精华内容 104,852
关键字:

引用计数

友情链接: LIMS_SSM-master.zip