引用计数

来源:互联网 发布:linux查询arp 编辑:程序博客网 时间:2024/05/16 14:31

当多个指针指向同一个对象,其中一个指针delete后,剩下的指针便成了野指针,浪费内存。
例如:

int *p = new int(3);int *p1 = p;int *p2 = p1;cout << *p1 << "  " << *p2 << endl;delete p;cout << *p1 << "  " << *p2 << endl;

这里写图片描述
因此,我们引入引用计数,我个人理解原理如此:设初始对象为t1,计数为1,对象t2指向t1,则t1计数+1,代表有两个对象指向该内存,而t2则-1,因为t2指向t1,若t2=0,则对t2进行销毁。

代码实现:
计数类实现

class count{template<typename T>friend class smart_ptr<T>; //智能指针类模板,用于判断是否销毁对象private:int *c;public:count():c(new int(1));count(count&r)//新对象一开始便指向已有对象,即直接调用复制构造函数{    c=r.c;    ++*r.c;}count &operator =(count &r)//已存在对象t1指向已存在对象t2,t1,-1;t2,+1.{    if(--*c==0)        delete c;    c=r.c;    r.c++;}bool selfcopy(count &r)//用于接下来smart_ptr赋值重载判断.{    ++*r.c;    if(--*c==0)    {        deleter c;        c=r.c;        return true;    }    c=r.c    return false;}bool only()//用于smart_ptr类析构判断。{    if(*c==1)        return true;    return false;}~count(){    if(--*c==0)     //多个对象指向一个块内存,每个对象取消指向时调用析构对计数进行--,等于0时便销毁内存。        delete c;}};

智能指针类
使用模板,体现出泛型编程的好处,能够用于其他类,而不是仅仅一个类。

template<typename T>class smart_ptr {private:    T *point;    Count count;public:    smart_ptr() : point(new T) {}    smart_ptr(const T &p) : point(new T(p)) {}    smart_ptr(const smart_ptr &sp) : point(sp.point),count(sp.count) {}    smart_ptr &operator =(const smart_ptr &p)    {        if (count.selfcopy(p.count))        {            //throw "error";            delete  point;        }        //point = new T;        point = p.point;        return *this;    }    T* get()//通过该函数获得使用该模板的类的对象指针,用于访问该类的公有成员。    {        return point;    }    ~smart_ptr()    {        if (count.isemtpy())            delete point;    }   };

可以写一个类用于测试,必须写复制构造函数,不重载赋值运算,不运用智能指针模板,多个对象指向同一个对象,被指向对象销毁时,编译器会报内存错误,运用模板后便可以达到销毁野对象的功能。
若想修改使用模板类的类的私有成员,且想让指向该类生成的对象,不会因为修改一个而其他对象的值都会变为同一个,即:

class A{private:int *x;public:A(int n=10){    x=new int[n];}void setx(int c);.......}main(){    smart_ptr<A>t(A());    smart_ptr<A>t1=t;    t.get()->setx(5);    t1.get()->setx(6);    //结果将全是6,因为指针都是指向同一个内存块,要是想不牵一发而动全身,则需要开辟新内存}想给指针开辟新内存,则在smart_ptr类中添加一个函数T* set();T* set(){    if(count.only())//仅有一个时直接返回该指针        return point;    point=new T(*(this->point));//给调用set()的对象开辟内存,关于为何是*(this->point),因为this为调用该函数对象指针,而point为使用模板类型T的指针,则*(this->point)为T类型对象。    return point;}则使用set()获取指针调用上述A类中的setx(n)可以修改值,为指向同一对象的其他调用set的对象开辟新内存。
0 0