智能指针

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

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

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);

       }

};

再来看一下拷贝



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

全部评论

相关推荐

03-03 23:42
复旦大学 Java
tongx_:闹呢,这找不到其他人还活不活
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 一张图晒出你司的标语 #
4356次浏览 77人参与
# AI面会问哪些问题? #
28127次浏览 565人参与
# 米连集团26产品管培生项目 #
13382次浏览 285人参与
# 你的实习产出是真实的还是包装的? #
20302次浏览 343人参与
# 找AI工作可以去哪些公司? #
9269次浏览 246人参与
# 春招至今,你的战绩如何? #
65914次浏览 584人参与
# 开放七大实习专项,百度暑期实习值得冲吗 #
15335次浏览 223人参与
# 从事AI岗需要掌握哪些技术栈? #
9098次浏览 319人参与
# 中国电信笔试 #
32033次浏览 293人参与
# 你做过最难的笔试是哪家公司 #
34008次浏览 244人参与
# 投递几十家公司,到现在0offer,大家都一样吗 #
340927次浏览 2175人参与
# 哪些公司真双非友好? #
69672次浏览 289人参与
# 阿里笔试 #
178839次浏览 1317人参与
# 机械人避雷的岗位/公司 #
62708次浏览 393人参与
# 小马智行求职进展汇总 #
25139次浏览 80人参与
# 第一份工作一定要去大厂吗 #
14817次浏览 122人参与
# 金三银四,你的春招进行到哪个阶段了? #
22158次浏览 280人参与
# 为了减少AI幻觉,你注入过哪些设定? #
26269次浏览 310人参与
# 应届生第一份工资要多少合适 #
20692次浏览 86人参与
# 沪漂/北漂你觉得哪个更苦? #
9990次浏览 194人参与
# 聊聊你的职场新体验 #
336545次浏览 1895人参与
# HR最不可信的一句话是__ #
6325次浏览 114人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务