智能指针

当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。那么智能指针是什么呢?智能指针是存储指向动态分配(堆)对象指针的类。

很多人都以为智能指针是一个指针,但其实它是一个模板,它可以自动释放所指向的对象。我们来看一下:

1.    Auto_ptr

auto_ptr在STL中早就存在了,auto_ptr是通过权限转移的方式来防止值拷贝所带来

的问题,所谓权限转移就是说开辟的动态内存任何时刻只能由一个指针指向。

#include<iostream>

using namespacestd;

template <classT>

class Auto_ptr {

private:

       T *ptr;

public:

       Auto_ptr(T *p)

              :ptr(p)

       {}

       ~Auto_ptr()

       {

              delete ptr;

       }

};

void main()

{

       Auto_ptr<int> p(new int(1));

       Auto_ptr<int> p1(new int(1));

       p1 = p;

}

在主函数中,我们使p1=p,可以发现它出现了bug,这是因为Auto_ptr是支持复制的,但是两个Auto_ptr都包括了一个指针,当它们析构的时候,同一个指针就会被析构两次,当然会出现问题。我们应该怎样解决呢?再来看:

#include<iostream>

using namespacestd;

template<class T>

class Auto_ptr{

private:

    T *ptr;

    bool owner;

public:

    Auto_ptr(T *p)

       :ptr(p),owner(true)

    {}

    ~Auto_ptr()

    {

       if (owner)

       {

           delete ptr;

       }

    }

    Auto_ptr(Auto_ptr &p)

    {

       ptr = p.ptr;

       owner = p.owner;

       p.owner = false;

    }

    Auto_ptr &operator=(Auto_ptr &p)

    {

       if (this != &p)

       {

           if (owner)

           {

              delete ptr;

           }

           ptr = p.ptr;

           owner = p.owner;

           p.owner = false;

       }

       delete p;

       return this;

    }

};

voidmain()

{

    Auto_ptr<int> p(new int(1));

    Auto_ptr<int> p1(p);

}

为了防止拷贝,又引入了scoped_ptr,就是把拷贝构造函数在private中定义,或者只在public中声明,但不写它的定义,意思就是使其不能拷贝。

为了更方便,我们又引入了shared_ptr,它的思想就是“引用计数”,每次有一个shared_ptr关联到某个对象上时,计数值就加上1;相反,每次有一个shared_ptr析构时,相应的计数值就减去1。当计数值减为0的时候,就执行对象的析构函数,此时该对象才真正被析构!

 

#include<iostream>

using namespace std;

template <class T>

class Shared_ptr {

private:

       T*ptr;

       int*count;

public:

       Shared_ptr(T*p)

              :ptr(p),count(new int(1))

       {}

       Shared_ptr(Shared_ptr&p)

              :ptr(p.ptr)

              ,count(p.count)

       {

              ++(*count);

       }

       ~Shared_ptr()

       {

              if(!(--(*count)))

              {

                     deleteptr;

                     deletecount;

                     ptr= NULL;

                     count= NULL;

                     cout<< "~Shared_ptr()" << endl;

              }

       }

       Shared_ptr&operator=(Shared_ptr &p)

       {

              if(ptr != p.ptr)//不能用this!=&p判断,因为有可能是多个指向相同的空间的指针进行的赋值

              {

                     if((*count) == 1)

                     {

                            deleteptr;

                            deletecount;

                     }

                     ptr= p.ptr;

                     count= p.count;

                     ++(*count);

              }

              returnthis;

       }

};

struct BB {

       intdata;

       Shared_ptr<BB>next;

       Shared_ptr<BB>pre;

       BB()

              :data(0)

              ,next(NULL)

              ,pre(NULL)

       {}

};

void main()

{

       Shared_ptr<BB>p(newBB());

       Shared_ptr<BB>p1(new BB());

}

这个结果就是:

~Shared_ptr()

~Shared_ptr()

~Shared_ptr()

~Shared_ptr()

~Shared_ptr()

~Shared_ptr()

为什么会析构六次呢,我们来画个图看一下


如果把主函数的两行代码改成

p->next = p1;

p1->pre = p;

就会得到:

~Shared_ptr()

~Shared_ptr()

这是为什么呢?



因为Shared_ptr(强引用)不能循环引用,所以又引入了Weak_ptr(弱引用)

template <class T>

class Weak_ptr {

private:

       T*ptr;

public:

       Weak_ptr(T*p)

              :ptr(p)

       {}

       ~Weak_ptr()

       {

              deleteptr;

       }

       Weak_ptr&opreator = (Shared_ptr<T> &p)

       {

              ptr= p.ptr;

              return*this;

       }

}

*在使用的时候必须将Weal_ptr声明为Shared_ptr的友元类。

看一下仿函数:

#include<iostream>

using namespace std;

struct com {

       booloperator()(int a, int b)

       {

              return(a > b);

       }

};

int main()

{

       comc;

       cout<< c(1, 2) << endl;

}

我们可以使用仿函数来定制删除器:

#include<iostream>

using namespace std;

//普通删除器

struct Del {

       voidoperator()(void *p)

       {

              deletep;

       }

};

//文件删除器

struct Del2 {

       voidoperator()(FILE *p)

       {

              fclose(p);

       }

};

再来看一下拷贝



就这么多咯。(*^▽^*)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值