建设工程标准在线网站,在线咨询网站模板,网页图片提取工具,怎么引导做淘宝的客户做官方网站目录
一、先来看一下什么是智能指针
二、 auto_ptr 1、C98版本
2、C11的auto_ptr
三、boost 库中的智能指针
1. scoped_ptr
2、shared_ptr#xff08;最好的智能指针#xff09;
四、C11中新提供的智能指针
unique_ptr
shared_ptr
std::shared_ptr的循环引用问题…目录
一、先来看一下什么是智能指针
二、 auto_ptr 1、C98版本
2、C11的auto_ptr
三、boost 库中的智能指针
1. scoped_ptr
2、shared_ptr最好的智能指针
四、C11中新提供的智能指针
unique_ptr
shared_ptr
std::shared_ptr的循环引用问题
weak_ptr弱指针 shared_ptr 定制删除器 智能指针真强大 一、先来看一下什么是智能指针 智能 可以看到我们在申请资源之后并没有进行手动释放但是却没有内存的泄漏 指针 他明明是个对象但用起来却像指针一样
可以发现智能指针是很神奇的下面让我们来看看他是怎样做到这些的吧 二、 auto_ptr 1、C98版本
原理如下类中含有两个成员 模拟 C98有着很大的缺陷主要就是拥有权的问题
当拥有权转移之后原来的还能去访问到数据这显然是一种藕断丝连的现象 这就导致了一种错觉仿佛转移之后还拥有着使用权 2、C11的auto_ptr
我们来看看C11对这种现象是怎么处理的 我们可以发现C11就改进了这一点不存在藕断丝连这一说了 三、boost 库中的智能指针
1. scoped_ptr
这个指针是个局部智能指针就像个“貔貅”一样只进不出不允许拥有权的转移构造拷贝都无法进行底层是一个普通的指针 模拟实现
templateclass T
class scoped_ptr
{
public:scoped_ptr(T* p 0) : px(p){}~scoped_ptr(){//检查释放//boost::checked_delete( px );delete px;}
public:T operator*() const{return *px;}T* operator-() const{return px;}T* get() const{return px;}
public:typedef scoped_ptrT this_type;void reset(T* p 0){//构造一个无名临时对象this_type(p).swap(*this);//this_type(p) scoped_ptrT(p);}void swap(scoped_ptr b) // never throws{T* tmp b.px;b.px px;px tmp;}
private:scoped_ptr(scoped_ptr const);scoped_ptr operator(scoped_ptr const); //私有的设置不允许拷贝赋值void operator(scoped_ptr const) const;void operator!(scoped_ptr const) const;
private:T* px;
}; 2、shared_ptr最好的智能指针
底层原理图内部是有一个引用计数器
引用计数器和之前学过的写实拷贝的地方实现原理很相似 功能 允许拷贝赋值 还可以输出有几个引用 模拟实现
实现这个shared_ptr 智能指针 需要有四个类
1. class shared_ptr类 #includeshared_count.hnamespace zyf
{templateclass Tclass shared_ptr{typedef shared_ptrT this_type;public:shared_ptr():px(0){}templateclass Yshared_ptr(Y* p) : px(p), pn(p){
#ifdef DISPLAYcout Created shread_ptr obj. endl;
#endif}~shared_ptr(){
#ifdef DISPLAYcout Free shread_ptr obj. endl;
#endif}shared_ptr operator(const shared_ptr r){this_type(r).swap(*this);return *this;}shared_ptr(const shared_ptrT r):px(r.px),pn(r.pn){}public:long use_count()const{return pn.use_count();}public:T operator*()const{return *px;}public:void swap(shared_ptrT other){std::swap(px, other.px);pn.swap(other.pn);}private:T* px;shared_count pn;//引用计数器对象};
}
2. shared_count 类
//引用计数器类
class shared_count
{
public:shared_count():pi_(0){}templateclass Yshared_count(Y *p):pi_(0){pi_ new sp_counted_implY(p);//多态
#ifdef DISPLAYcout Created shread_count obj. endl;
#endif}~shared_count(){
#ifdef DISPLAYcout Free shread_count obj. endl;
#endifif (pi_)pi_-release();}shared_count(const shared_count r):pi_(r.pi_){if (pi_ ! 0)pi_-add_ref_copy();}public:long use_count()const{if (pi_ nullptr)return 0;return pi_-use_count(); }
public:void swap(shared_count r){sp_counted_base* tmp r.pi_;r.pi_ pi_;pi_ tmp;}
private:sp_counted_base* pi_;
};
3. sp_counted_base类
class sp_counted_base
{
public:sp_counted_base() :use_count_(1){
#ifdef DISPLAYcout Created sp_counted_base obj endl;
#endif}virtual ~sp_counted_base(){
#ifdef DISPLAYcout Free sp_counted_base obj endl;
#endif}
public:void add_ref_copy(){use_count_;}void release(){if (--use_count_ 0){delete this;}}long use_count()const{return use_count_;}
private:long use_count_;};
4.sp_counted_impl类 这个类是继承 sp_sounted_base 类的
#includesp_counted_base.htemplateclass X
class sp_counted_impl : public sp_counted_base
{
public:sp_counted_impl(X *px):px_(px){
#ifdef DISPLAYcout Created sp_sounted_impl obj. endl;
#endif}~sp_counted_impl(){delete px_;
#ifdef DISPLAYcout Free sp_sounted_impl obj. endl;
#endif}
private:X* px_;
}; 四、C11中新提供的智能指针
unique_ptr
和scoped_ptr 一样 不允许拥有权的转移,和“貔貅”一样 shared_ptr
std::shared_ptr的线程安全问题
这里的线程不安全问题和之前的黄牛抢票现象是一样的 std::shared_ptr的循环引用问题
这里我们用一个双向列表的例子来举例说明什么是循环引用 我们先只创建两个节点类型观察一下情况会是什么样子的。 我们发现构造和析构函数能够正确的被调用没有出现问题
这时候我们再来将这两个节点连接起来观察一下会是怎么样的 我们很神奇的发现不连还好一连就出问题析构函数没有被调用这是什么情况呢我们来探究一下 在函数调用结束后释放node1和node2智能指针所指向的资源的时候会给两个资源的计数器都减减但是也只是减为1两个节点内部的指针相互指向到最后谁都释放不了。
根本原因 节点相互连接赋值的时候因为内部的prev和 next 和节点的 node类型是一种类型导致引用计数器会增加 weak_ptr弱指针
解决这里的办法就是使用weak_ptr
weak_ptr 是为配合 shared ptr 而引入的一种智能指针它更像是 shared ptr 的一个助手而不是智能指针因为它不具有普通指针的行为没有重载 operator*和-。它的最大作用在于协助 shared ptr 工作像旁观者那样观测资源的使用情况。 上面我们知道了使用weak_ptr 可以不增加引用计数
使用了weak_ptr之后我们再来看看会是怎么样的 shared_ptr 定制删除器 智能指针真强大
只要共享性智能指针对象的释放方式不能满足我们的要求我们就可以取定制一个
1. 遇到数组类型的空间 这时候可以定制一个删除器 这时候就解决问题了 2. 还可以解决不是new 出来的空间问题
比如是malloc出来的这时候应该用free去对应 其他问题也可以 比如是文件描述符 socketfd 、 newsockfd 、fp