精华内容
下载资源
问答
  • weak_ptr实现原理
    千次阅读
    2019-08-07 00:53:51

    weak_ptr描述

    声明

    头文件:<memory>
    模版类:template <class T> class weak_ptr
    声明方式:std::weak_ptr<type_id> statement

    作用

    根据boost库的官方描述,weak_ptr是由shared_ptr管理的一种弱引用对象的模版类。weak_ptr的对象能够使用shared_ptr指针的构造函数转换为一个shared_ptr对象。但是这里shared_ptr的构造函数参数需要包含weak_ptr的lock成员,该成员是weak_ptr用来获取shared_ptr的指针。

    这样当shared_ptr在多线程过程中被销毁时shared_ptr::reset,weak_ptr的lock成员仍然能够保留shared_ptr的成员,直到当前shared_ptr正常终止,否则会出现非常危险的内存泄漏。关于lock()成员的作用如下描述:
    如下代码

    shared_ptr<int> p(new int(5));
    weak_ptr<int> q(p);
    
    // some time later
    
    if(int * r = q.get()) 
    {
        // use *r
    }
    

    多线程环境中shared_ptr是可以被多个线程共享,在r被使用之前p对象执行了p.reset(),正如我们上一篇文章中对shared_ptr的描述(C++智能指针:shared_ptr 实现详解),reset成员会重置当前shared_ptr指针的指向。此时,当前线程如果继续使用r指针,势必会产生访问空地址的异常问题

    根据以上问题,使用weak_ptr::lock()成员来解决该问题

    shared_ptr<int> p(new int(5));
    weak_ptr<int> q(p);
    
    // some time later
    
    //使用weak_ptr的lock成员来获取shared_ptr的指针
    if(shared_ptr<int> r = q.lock())
    {
        // use *r
    }
    

    关于lock()成员简单说明一下,lock成员获取到的shared_ptr p指针创建一个临时对象(我们weak_ptr弱引用的体现),这个临时对象同样指向p,即使p执了reset这样的delete引用的操作,弱引用对象仍然持有改智能指针的地址,直到r指针的生命周期结束才会释放。不得不佩服C++语言设计者的脑洞,为了保持C++对内存操作的自由,即使耗费再大的精力也要实现这一目标,工匠精神才让今天的C++越来越被底层程序员喜欢。

    原理实现

    源码文件/boost/smart_ptr/weak_ptr.hpp

    template<class T> class weak_ptr
    {
    private:
    
        // Borland 5.5.1 specific workarounds
        typedef weak_ptr<T> this_type;
    
    • constructor 构造函数
      //默认构造函数
      weak_ptr() BOOST_NOEXCEPT : px(0), pn() // never throws in 1.30+
      {
      }
      
      //拷贝构造函数
      weak_ptr( weak_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
      {
      }
      
    • destructor析构函数,这里weak_ptr使用的是默认析构函数,一般使用expired返回空对象或者user_count()为0的情况则辅助shared_ptr释放引用
    • operator=
      1. 
       weak_ptr & operator=( weak_ptr && r ) BOOST_NOEXCEPT
      {
          this_type( static_cast< weak_ptr && >( r ) ).swap( *this );
          return *this;
      }
      
      //2.这里会更加安全,使用lock成员获取Y类型的指针
      template<class Y>
      weak_ptr & operator=( weak_ptr<Y> const & r ) BOOST_NOEXCEPT
      {
          boost::detail::sp_assert_convertible< Y, T >();
      
          px = r.lock().get();
          pn = r.pn;
      
          return *this;
      }
      
      3.
      template<class Y>
      weak_ptr & operator=( shared_ptr<Y> const & r ) BOOST_NOEXCEPT
      {
          boost::detail::sp_assert_convertible< Y, T >();
      
          px = r.px;
          pn = r.pn;
      
          return *this;
      }
      
    • weak_ptr::swap成员,交换两个weak_ptr所指内容以及地址
       void swap(this_type & other) BOOST_NOEXCEPT
      {
      	//先交换地址,再交换内容
          std::swap(px, other.px);
          pn.swap(other.pn);
      }
      
    • weak_ptr::reset成员,·重新指定对象地址和内容,就像是重新使用默认构造函数进行了初始化
      void reset() BOOST_NOEXCEPT // never throws in 1.30+
      {
      	//使用默认构造函数构造的对象和当前对象进行swap操作
          this_type().swap(*this);
      }
      
    • weak_ptr::use_count成员,获取shared_ptr对象被引用的次数。如果为空,则返回0
      long use_count() const BOOST_NOEXCEPT
      {
          return pn.use_count();
      }
      
    • weak_ptr::expired成员,当根据use_count==0来返回bool,其返回为true的时候,使用lock获取weak_ptr的指针只能获取到空指针
       bool expired() const BOOST_NOEXCEPT
      {
          return pn.use_count() == 0;
      }
      
    • weak_ptr::lock成员,会向weak_ptr对象返回一个shared_ptr。正如我们之前在weak_ptr作用中所描述的,防止多线程访问时的shared_ptr内存泄漏。此时weak_ptr对象获取到的指针为临时指针,会指向shared_ptr对象之前所指向的地址。
      shared_ptr<T> lock() const BOOST_NOEXCEPT
      {
          return shared_ptr<T>( *this, boost::detail::sp_nothrow_tag() );
      }
      

    函数成员使用

    • 构造函数
      #include <iostream>
      #include <memory>
      
      struct C {int* data;};
      
      int main () {
        std::shared_ptr<int> sp (new int);
      
        std::weak_ptr<int> wp1;
        std::weak_ptr<int> wp2 (wp1);
        std::weak_ptr<int> wp3 (sp);
      
        std::cout << "use_count:\n";
        
        //weak_ptr对象如果为经shared_ptr初始化,
        //它是没有引用计数的,所以这里wp1和wp2引用计数都为0
        //只有wp3经过了shared_ptr初始化,它的引用计数才为1
        
        std::cout << "wp1: " << wp1.use_count() << '\n';
        std::cout << "wp2: " << wp2.use_count() << '\n';
        std::cout << "wp3: " << wp3.use_count() << '\n';
        
        return 0;
      }
      
      输出如下:
      use_count:
      wp1: 0
      wp2: 0
      wp3: 1
      
    • weak_ptr::operator=赋值运算符
      // weak_ptr::operator= example
      #include <iostream>
      #include <memory>
      
      int main () {
        std::shared_ptr<int> sp1,sp2;
        std::weak_ptr<int> wp;
                                             // sharing group:
                                             // --------------
        sp1 = std::make_shared<int> (10);    // sp1
        wp = sp1;                            // sp1, wp
      
        sp2 = wp.lock();                     // sp1, wp, sp2
        sp1.reset();                         //      wp, sp2
      
        //通过lock保留的临时指针,重新获取到了shared_ptr共享的地址
        sp1 = wp.lock();                     // sp1, wp, sp2
      
        std::cout << "*sp1: " << *sp1 << '\n';
        std::cout << "*sp2: " << *sp2 << '\n';
      
        return 0;
      }
      
      输出如下
      *sp1: 10
      *sp2: 10
      
    • std::weak_ptr::swap交换指针地址以及对应的内容
      #include <iostream>
      #include <memory>
      
      int main () {
        std::shared_ptr<int> sp1 (new int(10));
        std::shared_ptr<int> sp2 (new int(20));
      
        std::weak_ptr<int> wp1(sp1);
        std::weak_ptr<int> wp2(sp2);
        
        std::cout << "wp1 -> " << *wp1.lock() << " " << wp1.lock() << '\n';
        std::cout << "wp2 -> " << *wp2.lock() << " " << wp2.lock() << '\n';
      
        //这里的swap仅仅是交换wp2的各自的指向地址
        //并不会直接导致对应智能指针原始指针的地址交换
        //根据输出,所以很明显,交换完成之后weak_ptr对象指向发生了变化,但是并未导致share_ptr指针的指向变化
        wp1.swap(wp2);
      
        std::cout << "sp1 -> " << *sp1 << " " << sp1 << '\n';
        std::cout << "sp2 -> " << *sp2 << " " << sp2 << '\n';
        std::cout << "wp1 -> " << *wp1.lock() << " " << wp1.lock() << '\n';
        std::cout << "wp2 -> " << *wp2.lock() << " " << wp2.lock() << '\n';
      
        return 0;
      }
      
      输出如下:
      wp1 -> 10 0x11daf90
      wp2 -> 20 0x11dafd0
      sp1 -> 10 0x11daf90
      sp2 -> 20 0x11dafd0
      wp1 -> 20 0x11dafd0
      wp2 -> 10 0x11daf90
      
    • std::weak_ptr::reset成员,执行之后weak_ptr对象就像是重新执行了默认构造函数,又变成了一个空的对象
      // weak_ptr::reset example
      #include <iostream>
      #include <memory>
      
      int main () {
        std::shared_ptr<int> sp (new int(10));
      
        std::weak_ptr<int> wp(sp);
      
        std::cout << "1. wp " << (wp.expired()?"is":"is not") << " expired\n";
        std::cout << "4. wp " << wp.use_count() << " *wp " << *wp.lock() << '\n';
      
        wp.reset();
      
        std::cout << "2. wp " << (wp.expired()?"is":"is not") << " expired\n";
        std::cout << "3. sp " << sp.use_count() << " *sp " << *sp << '\n';
      
        return 0;
      }
      
      输出如下
      1. wp is not expired
      2. wp 2 *wp 10
      3. wp is expired
      4. sp 1 *sp 10
      

    总结

    shared_ptr和weak_ptr主要区别如下

    1. shared_ptr对象能够初始化实际指向一个地址内容而weak_ptr对象没办法直接初始化一个具体地址,它的对象需要由shared_ptr去初始化
    2. weak_ptr不会影响shared_ptr的引用计数,因为它是一个弱引用,只是一个临时引用指向shared_ptr。即使用shared_ptr对象初始化weak_ptr不会导致shared_ptr引用计数增加。依此特性可以解决shared_ptr的循环引用问题。
    3. weak_ptr没有解引用*和获取指针->运算符,它只能通过lock成员函数去获取对应的shared_ptr智能指针对象,从而获取对应的地址和内容。

    参考文档:
    http://www.cplusplus.com/reference/memory/weak_ptr/
    https://www.boost.org/doc/libs/1_66_0/libs/smart_ptr/doc/html/smart_ptr.html#weak_ptr

    更多相关内容
  • C++ 11中最常用的智能指针类型为shared_ptr,它采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆上分配。当新增一个时引用计数加1,当过期时引用计数减一。只有引用计数为0时,智能...
  • 主要介绍了 C++11智能指针之weak_ptr详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • c++智能指针总结 一、智能指针出现的原因 1. 基于我们的的编程习惯,在堆区动态管理的资源忘记释放或者回收了,导致内存泄漏。 2. 有多个指针指向同一...二、智能指针的本质及其原理 智能指针的本质一个对象,是一个

    c++智能指针总结

    一、智能指针出现的原因

    1. 基于我们的的编程习惯,在堆区动态管理的资源忘记释放或者回收了,导致内存泄漏。
    2. 有多个指针指向同一片内存的问题,造成内存资源的重复释放或回收。
    3. 程序在在抛出异常前申请了资源,以至于异常抛出时导致程序中断,无法执行析构函数delete内存从而导致的内存泄漏。

    基于上面三个主要的原因,聪明的程序员就提出了智能指针方便管理我们自己的内存,一定程度上解决了c++为了人所诟病的内存管理问题。
    注意:三种指针包含在头文件< memory >.

    二、智能指针的本质及其原理

    • 智能指针的本质一个对象,是一个行为表现都像指针的对象。它的封装利用了RAII机制或者思想,其RAII机制或者思想是“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。
    • 智能指针可分为两部分,一个是原指针,一个是引用计数(关联的计数器)。创建一个智能指针的时候引用计数为1,当引用计数为0的时候,智能指针本身会自动释放。当该智能指针被其他指针所用,引用计数就会相应的叠加,可以这么理解:引用计数的大小就是当前管理该内存的指针的数量。

    三、三种智能指针的介绍

    1.shared_ptr

    1.初始化和赋值(注意不要用一个原始指针初始化多个shared_ptr 会导致重复释放内存)

    #include <memory>
    #include<iostream>
    int main() {
    	int* a = new int(10);
    	std::shared_ptr<int>s1(a);
    	std::shared_ptr<int>s2(new int(10));
    	std::shared_ptr<int>s3 = s1;
    	std::shared_ptr<int>s4=make_shared<int>(30);
    	auto s5 = std::make_shared<int>(20);	
    	return 0;
    }
    

    2.重载原始指针的“*”和“->”

    #include <memory>
    #include<iostream>
    class Person
    {
    public:
    	Person(int a) :a(a){}
    public:
    	int a;
    };
    int main() {
    	std::shared_ptr<Person>s(new Person(2));
    	//与原始指针的使用方式一样
    	std::cout << (*s).a << std::endl;
    	std::cout << s->a << std::endl;
    		return 0;
    }
    

    3.其他成员函数的作用和使用

    #include <memory>
    #include<iostream>
    #include<algorithm>
    class Person
    {
    public:
    	Person(int a) :a(a){}
    public:
    	int a;
    };
    int main() {
    	std::shared_ptr<Person>s(new Person(2));
    	std::cout << (*s).a << std::endl;
    	std::cout << s->a << std::endl;
    
    	std::cout << s.use_count() << std::endl;//得到引用计数的数量即当前管理该内存的指针的个数
    	Person*p = s.get();//得到原始的指针
    
    	std::shared_ptr<Person>s2 = s;
    	std::cout << s.use_count() << std::endl;
    	s.~shared_ptr();//析构函数它的作用是use_count()--然后其检查是否为0 若为0就释放,若不为0选择无视
    	std::cout << s2.use_count() << std::endl;//此处打印为1说明上面析构函数没有释放内存资源
    	
    	std::shared_ptr<Person>s3(new Person(4));
    	s3.swap(s2);//交换管理的内存,交换指针
    	swap(s2, s3);//跟上面效果一样
    
    	if (s2.unique())std::cout << "资源是被唯一管理的" << std::endl; //用来判断资源是否是被唯一管理的
    
    	s2.reset();//强制释放资源,将s2的use_count()置为0 指针指向nullptr
    	s3.reset(new Person(10));//重置资源
    	std::cout<< s3->a<< std::endl;
    
    	return 0;
    }
    

    2.weak_ptr

    关于弱指针,我们先要追究一下它的来由,看下面代码:

    #include <memory>
    #include<iostream>
    class Son;
    class Father;
    using fatherptr = std::shared_ptr<Father>;
    using sonptr = std::shared_ptr<Son>;
    class Father
    {
    public:
    	sonptr s;
    	Father();
    	~Father();
    };
    class Son
    {
    public:
    	fatherptr f;
    	Son();
    	~Son();
    };
    
    Father::Father() { std::cout << "hello father"<<std::endl; }
    Father::~Father() { std::cout << "bye father"<<std::endl;}
    Son::Son() { std::cout << "hellow son"<<std::endl; }
    Son::~Son() { std::cout << "bye son" << std::endl; }
    
    using fatherptr = std::shared_ptr<Father>;
    using sonptr = std::shared_ptr<Son>;
    int main() {
    
    	fatherptr f(new Father());
    	sonptr s(new Son());
        f->s = s;
        s->f = f;  //循环调用
    
    	std::cout << f.use_count() << std::endl;//输出2
    	std::cout << s.use_count() << std::endl;//输出2
    
        return 0;
    }
    

    有如下结果:
    在这里插入图片描述
    发现它并没有调用智能指针指向的对象的析构函数!!为啥呢??
    原因是:在智能指针调用析构函数的时候先将use_count- -当use_count等于0的时候,释放所指对象的内存资源,但是这里它发现use_count等于1,相当于给它传递一个信息,还有指针在用这一片资源,不能释放!从而导致了这里内存的泄露,这也是share_ptr在这种循环调用中的缺陷!!

    那么怎么解决,聪明的程序员就开发出了weak_ptr,可以这么说,weak_ptr就是为了协助share_ptr而生。它本身不具备指针的功能没有重载的“*”和“->”.
    它的成员函数都是为了监测shared_ptr所管理的资源而设计的。

    #include <memory>
    #include<iostream>
    class Person
    {
    public:
    	Person(int a) :a(a) {}
    public:
    	int a;
    };
    int main() {
    	std::shared_ptr<Person>s(new Person(2));
    	std::weak_ptr<Person>w = s;
    	std::weak_ptr<Person>w2(s);
    	std::weak_ptr<Person>w3(w2);   //weak_ptr从一个shared_ptr或者weak_ptr进行对象构造的初始化
    
    	std::cout << s.use_count() << std::endl;//输出为1,说明weak_ptr构造它的时候引用计数不会增加
    	                                        //weak_ptr没有参与资源管理,只是对资源的监控
    	std::cout << w2.use_count() << std::endl;
    
    	auto s2 = w.lock();//返回一个指向该资源的shared_ptr
    	
    	if(w.expired())//判读weak_ptr监控的shared_ptr是不是空资源 相当于use_cout==0,但是这种方式更快
    	{std::cout<<"shared_ptr指向的是空区域"<<std::endl; }
    	else
    	{std::cout<<"shared_ptr管理的资源不是空" ;}
    	
    	return 0;
    }
    

    那等于循环调用 我们如何通过弱指针来解决呢?

    #include <memory>
    #include<iostream>
    #include<algorithm>
    
    class Son;
    class Father;
    using fatherptr = std::shared_ptr<Father>;
    using sonweakptr = std::weak_ptr<Son>;
    using sonptr = std::shared_ptr<Son>;
    class Father
    {
    public:
    	sonweakptr s;
    	Father();
    	~Father();
    };
    class Son
    {
    public:
    	fatherptr f;
    	Son();
    	~Son();
    };
    
    Father::Father() { std::cout << "hello father"<<std::endl; }
    Father::~Father() { std::cout << "bye father"<<std::endl;}
    Son::Son() { std::cout << "hellow son"<<std::endl; }
    Son::~Son() { std::cout << "bye son" << std::endl; }
    
    int main() {
    
    	fatherptr f(new Father());
    	sonptr s(new Son());
        f->s = s;
        s->f = f;  //循环调用
    
    	std::cout << f.use_count() << std::endl;
    	std::cout << s.use_count() << std::endl;
    
        return 0;
    }
    

    我们把其中一个成员指针改成弱指针,就有如下结果:
    在这里插入图片描述

    这样就解决了shared_ptr循环调用的问题。

    3.unique_ptr

    unique顾名思义,唯一的指向一个对象,该对象不能被共享(指针和资源一对一),unique_ptr向比于原始指针,使得在出现异常的情况下动态资源得以释放,unique_ptr的释放规则是:unique_ptr从指针开始,到离开作用域时,释放其指向的对象资源。
    unique_ptr用法:

    #include<iostream>
    #include<memory>
    int main()
    {
    	std::unique_ptr<int> u(new int(10));//绑定申请的堆区资源
    	std::unique_ptr<int>u2(std::move(u));//转移所有权到u2(移动语义) 
    	
    	//不允许同一份资源,被多个unique_Ptr管理
    	//std::unique_ptr<int>u2(u);不能拷贝
    	//std::unique_ptr<int>u3=u;不能赋值
    
    	auto p=u.release();//释放所有权 返回原指针,相当于unique_ptr不参与原指针的管理了
    	u.reset(new int(20));//重新制定所有权
    	std::shared_ptr s(std::move(u2));//在有需要的时候,我们也可以将它转移到shared_ptr中管理。
    
    }
    

    其余操作和shared_ptr类似。

    shared_ptr常见错误补充

    如果我们想在类的内部调用自身的智能指针,我们肯定会想到用this指针初始化一个智能指针,如下面的代码:

    #include <memory>
    #include<iostream>
    #include<algorithm>
    class Son;
    class Father;
    using fatherptr = std::shared_ptr<Father>;
    using faweakptr = std::weak_ptr<Father>;
    using sonweakptr = std::weak_ptr<Son>;
    using sonptr = std::shared_ptr<Son>;
    void handptr(const fatherptr& f, const sonptr& s)//增加测试函数作为 作为类中成员函数调用自身智能指针的定义实现
    {
    	std::cout << "测试函数" << std::endl;
    }
    class Father
    {
    public:
    	sonweakptr s;
    	Father();
    	~Father();
    	void test();
    };
    class Son
    {
    public:
    	fatherptr f;
    	Son();
    	~Son();
    };
    
    Father::Father() { std::cout << "hello father"<<std::endl; }
    Father::~Father() { std::cout << "bye father"<<std::endl;}
    void Father::test() { handptr(fatherptr(this), s.lock()); }//在类内部成员函数调用自身智能指针
    Son::Son() { std::cout << "hellow son"<<std::endl; }
    Son::~Son() { std::cout << "bye son" << std::endl; }
    
    int main() {
    
    	fatherptr f(new Father());
    	sonptr s(new Son());
        f->s = s;
        s->f = f;  
    	f->test();//调用测试
    
    	std::cout << f.use_count() << std::endl;
    	std::cout << s.use_count() << std::endl;
    
        return 0;
    }
    

    我们会有如下结果:
    在这里插入图片描述
    发生了意料之中的错误,听一片内存被释放了两次。
    这时候我们就要引入新知识std::enable_shared_from_this,这是一个模板类,用法代码如下:

    #include <memory>
    #include<iostream>
    #include<algorithm>
    class Son;
    class Father;
    using fatherptr = std::shared_ptr<Father>;
    using faweakptr = std::weak_ptr<Father>;
    using sonweakptr = std::weak_ptr<Son>;
    using sonptr = std::shared_ptr<Son>;
    void handptr(const fatherptr& f, const sonptr& s)//增加测试函数作为 作为类中成员函数调用自身智能指针的定义实现
    {
    	std::cout << "测试函数" << std::endl;
    }
    class Father:public std::enable_shared_from_this<Father>//继承该模板类,传入本身类型
    {
    public:
    	sonweakptr s;
    	Father();
    	~Father();
    	void test();
    };
    class Son:public std::enable_shared_from_this<Son>
    {
    public:
    	fatherptr f;
    	Son();
    	~Son();
    };
    
    Father::Father() { std::cout << "hello father"<<std::endl; }
    Father::~Father() { std::cout << "bye father"<<std::endl;}
    void Father::test() { handptr(shared_from_this(), s.lock()); }//传入父类的继承函数成员函数,该成员函数返回一个this的智能指针
    Son::Son() { std::cout << "hellow son"<<std::endl; }
    Son::~Son() { std::cout << "bye son" << std::endl; }
    
    int main() {
    
    	fatherptr f(new Father());
    	sonptr s(new Son());
        f->s = s;
        s->f = f;  
    	f->test();//调用测试
    
    	std::cout << f.use_count() << std::endl;
    	std::cout << s.use_count() << std::endl;
    
        return 0;
    }
    

    总结

    智能指针能给我们资源管理带来极大的便捷,但是凡是都有两面性,智能指针所带来的便捷,其实是由性能消耗换来的,在追求极致性能的时候,不要盲目使用智能指针。

    写了一个下午,给菜鸡一个👍鼓励一下吧~~

    展开全文
  • C++ 智能指针(shared_ptr/weak_ptr)源码 源码位置:gcc-6.1.0\gcc-6.1.0\libstdc++-v3\include\tr1 这里只单列shared_ptr.h文件用于分析
  • 智能指针原理剖析(一):auto_ptr、unique_ptr shared_ptr、weak_ptr原理剖析 关于shared_ptr源码剖析的博客有很多,推荐一篇讲解十分详细的博客:从源码理解智能指针(二)—— shared_ptr、weak_ptr。本文在此...

    智能指针原理剖析(一):auto_ptr、unique_ptr

    shared_ptr、weak_ptr原理剖析

    关于shared_ptr源码剖析的博客有很多,推荐一篇讲解十分详细的博客:从源码理解智能指针(二)—— shared_ptr、weak_ptr。本文在此基础上,对shared_ptr、weak_ptr实现的原理进行总结并画出类关系图,读者可结合两篇博客一起阅读,从而帮助理解。

    总体而言,实现shared_ptr、weak_ptr智能指针是通过两个基类_Ref_count_base、_Ptr_base以及它们的派生类来实现的,其结构图如下:
    在这里插入图片描述

    1、抽象类_Ref_count_base

    class _Ref_count_base
    	{	// common code for reference counting
    private:
    	virtual void _Destroy() = 0;
    	virtual void _Delete_this() = 0;
    
    private:
    	_Atomic_counter_t _Uses;  //强引用计数
    	_Atomic_counter_t _Weaks;  //弱引用计数
    
    protected:
    	_Ref_count_base()
    		{	// construct
    		_Init_atomic_counter(_Uses, 1);  //强引用计数初始化为1
    		_Init_atomic_counter(_Weaks, 1); //弱引用计数初始化为1
    		}
    
    public:
    	virtual ~_Ref_count_base() _NOEXCEPT  //虚析构函数
    		{	// ensure that derived classes can be destroyed properly
    		}
    
    	unsigned int _Get_uses() const  //获取强引用计数
    		{	// return use count
    		return (_Get_atomic_count(_Uses));
    		}
    		
    	void _Incref()
    		{	// increment use count
    		_MT_INCR(_Mtx, _Uses);// _Uses+1
    		}
     
    	void _Incwref()
    		{	// increment weak reference count
    		_MT_INCR(_Mtx, _Weaks);//_Weaks+1
    		}
    		
    	void _Decref()
    		{	// decrement use count
    		if (_MT_DECR(_Mtx, _Uses) == 0)
    			{	// destroy managed resource, decrement weak reference count
    			_Destroy(); //释放资源
    			_Decwref();
    			}
    		}
    
    	void _Decwref()
    		{	// decrement weak reference count
    		if (_MT_DECR(_Mtx, _Weaks) == 0)  //判断弱引用计数-1后是否为0
    			_Delete_this(); //删除计数器自身
    		}
    
    	long _Use_count() const  //返回强引用计数
    		{	// return use count
    		return (_Get_uses());
    		}
    
    	bool _Expired() const    //强引用计数是否为0
    		{	// return true if _Uses == 0
    		return (_Get_uses() == 0);
    		}
    
    	virtual void *_Get_deleter(const _XSTD2 type_info&) const
    		{	// return address of deleter object
    		return (0);
    		}
    	};
    

    _Ref_count_base是派生类_Ref_count、_Ref_count_del、_Ref_count_del_alloc的基类,是计数器的接口。基类中纯虚函数virtual void _Destroy() = 0、virtual void _Delete_this() = 0是实现多态的接口,具体定义在三个子类中实现,分别表示释放资源、删除计数器自身。

    _Uses是强引用计数,计算引用资源的shared_ptr个数,_Weaks是弱引用计数,计算引用资源的weak_ptr的个数。 _Uses和_Weaks的增加或减少,在底层中通过一条指令就可以实现,是原子操作

    类中封装了函数_Decref(),表示:若 引用计数 _Uses == 0,就调用_Destroy()来释放资源,并调用_Decwref()递减_Weaks。

    类中封装了函数_Decwref(),表示:若弱引用计数_Weaks= =0,就调用_Delete_this()来删除计数器自身。
    由_Ref_count_base类的源码可知,释放资源的条件为: _Uses== 0;删除计数器的条件为:_Uses== 0&&_Weaks==0。

    1.1、派生类_Ref_count

    template<class _Ty>
    	class _Ref_count
    	: public _Ref_count_base
    	{	// handle reference counting for object without deleter
    public:
    	_Ref_count(_Ty *_Px)
    		: _Ref_count_base(), _Ptr(_Px)
    		{	// construct
    		}
    
    private:
    	virtual void _Destroy()
    		{	// destroy managed resource
    		delete _Ptr;
    		}
    
    	virtual void _Delete_this()
    		{	// destroy self
    		delete this;
    		}
    
    	_Ty * _Ptr;
    	};
    

    Ref_count是_Ref_count_base的派生类,定义了资源释放函数_Destroy() 、删除计数器自身函数_Delete_this(),以及一个指向_Ty类型的指针_Ptr,由派生类_Ref_count生成对象时只能通过指针_Ptr来进行构造。

    1.2、派生类_Ref_count_del

    template<class _Ty,
    	class _Dx>
    	class _Ref_count_del
    	: public _Ref_count_base
    	{	// handle reference counting for object with deleter
    public:
    	_Ref_count_del(_Ty *_Px, _Dx _Dt)
    		: _Ref_count_base(), _Ptr(_Px), _Dtor(_Dt)
    		{	// construct
    		}
    
    	virtual void *_Get_deleter(const _XSTD2 type_info& _Typeid) const
    		{	// return address of deleter object
    		return ((void *)(_Typeid == typeid(_Dx) ? &_Dtor : 0));
    		}
    
    private:
    	virtual void _Destroy()
    		{	// destroy managed resource
    		_Dtor(_Ptr);
    		}
    
    	virtual void _Delete_this()
    		{	// destroy self
    		delete this;
    		}
    
    	_Ty * _Ptr;
    	_Dx _Dtor;	// the stored destructor for the controlled object 被控制对象的已析构函数
    	};
    

    Ref_count_del是_Ref_count_base的派生类,定义了资源释放函数_Destroy() 、删除计数器自身函数_Delete_this(),以及一个指向_Ty类型的指针_Ptr和_Dx类型的删除器_Dtor,由派生类_Ref_count生成对象时只能通过指针_Ptr和删除器_Dtor来进行构造。

    1.3、派生类_Ref_count_del_alloc

    template<class _Ty,
    	class _Dx,
    	class _Alloc>
    	class _Ref_count_del_alloc
    	: public _Ref_count_base
    	{	// handle reference counting for object with deleter and allocator
    public:
    	typedef _Ref_count_del_alloc<_Ty, _Dx, _Alloc> _Myty;
    	typedef typename _Alloc::template rebind<_Myty>::other _Myalty;
    
    	_Ref_count_del_alloc(_Ty *_Px, _Dx _Dt, _Myalty _Al)
    		: _Ref_count_base(), _Ptr(_Px), _Dtor(_Dt), _Myal(_Al)
    		{	// construct
    		}
    
    	virtual void *_Get_deleter(const _XSTD2 type_info& _Typeid) const
    		{	// return address of deleter object
    		return ((void *)(_Typeid == typeid(_Dx) ? &_Dtor : 0));
    		}
    
    private:
    	virtual void _Destroy()
    		{	// destroy managed resource
    		_Dtor(_Ptr);
    		}
    
    	virtual void _Delete_this()
    		{	// destroy self
    		_Myalty _Al = _Myal;
    		_Al.destroy(this);
    		_Al.deallocate(this, 1);
    		}
    
    	_Ty * _Ptr;
    	_Dx _Dtor;	// the stored destructor for the controlled object
    	_Myalty _Myal;	// the stored allocator for this
    	};
    

    Ref_count_del_alloc是_Ref_count_base的派生类,定义了资源释放函数_Destroy() 、删除计数器自身函数_Delete_this(),以及一个指向_Ty类型的指针_Ptr、_Dx类型的删除器_Dtor、_Myalty类型的分配器_Myal,由派生类_Ref_count生成对象时只能通过指针_Ptr、删除器_Dtor和分配器_Myal来进行构造。

    2、基类_Ptr_base

    基类_Ptr_base中含有两个成员变量,一个指向_Ty类型的指针_Ptr、一个指向_Ref_count_base类型的计数器指针_Rep。此处的指针_Ptr应与类_Ref_count_base下派生类中的_Ptr相同。
    _Ptr_base中的主要函数如下:

        _Ptr_base()  //无参构造函数
        _Ptr_base(_Myt&& _Right)    //移动构造函数
        template<class _Ty2> _Ptr_base(_Ptr_base<_Ty2>&& _Right)  //移动构造函数
        _Myt& operator=(_Myt&& _Right)   //移动赋值函数
        long use_count() const _NOEXCEPT  //获取强引用计数
        void  _Decref()  //调用_Rep->_Decref(),减少计数器的强引用计数
        void  _Decwref()  //调用_Rep->_Decwref(),减少计数器的弱引用计数
        void _Reset()及其重载版本   //重置当前shared_ptr,减少当前对象持有某资源的强引用计数,增加传入对象持有新资源的强引用计数
        void _Resetw()及其重载版本    //重置当前weak_ptr,减少当前对象持有某资源的弱引用计数,增加传入对象持有新资源的弱引用计数
    

    3、shared_ptr

    shared_ptr是基类_Ptr_base的派生类,也是用户生成共享智能指针的接口。shared_ptr封装了大量的构造函数、赋值函数,主要供用户构造对象使用:

    传参构造函数

      shared_ptr() _NOEXCEPT  //无参构造函数,调用基类默认构造函数,使_Ptr和_Rep均初始化为0
      template<class _Ux> explicit shared_ptr(_Ux *_Px)    //用资源指针_Px构造,调用_Ref_count,构造完成后强引用计数为1
      template<class _Ux,class _Dx> shared_ptr(_Ux *_Px, _Dx _Dt)//用资源指针和删除器来构造,调用_Ref_count_del,构造完成后强引用计数为1
      template<class _Dx> shared_ptr(nullptr_t, _Dx _Dt) //用nullptr和删除器来构造,调用_Ref_count_del,构造完成后强引用计数为1
      template<class _Dx,class _Alloc> shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax) //用nullptr、删除器、分配器来构造,调用_Ref_count_del_alloc,构造完成后强引用计数为1
      template<class _Ux,class _Dx,class _Alloc> shared_ptr(_Ux *_Px, _Dx _Dt, _Alloc _Ax) //用不同类型的资源指针、删除器及分配器来构造,调用_Ref_count_del_alloc,构造完成后强引用计数为1
    

    以上构造函数为传参构造函数:用于从无到有构造一个shared_ptr对象,同时生成一个计数器对象,构造完成后的引用计数和弱引用计数均为1

    拷贝构造函数

     template<class _Ty2> shared_ptr(const shared_ptr<_Ty2>& _Right, _Ty *_Px) _NOEXCEPT  //传入shared_ptr对象和新的资源指针对构造对象,_Right的引用计数不会改变
     shared_ptr(const _Myt& _Other) _NOEXCEPT  //拷贝构造,传入shared_ptr对象,当前对象绑定_Other的资源指针和计数器,引用计数+1
     template<class _Ty2> explicit shared_ptr(const weak_ptr<_Ty2>& _Other,bool _Throw = true)  //用weak_ptr对象来构造shared_ptr,若成功,二者共享资源指针以及计数器,强引用计数+1,否则抛出异常
     template<class _Ty2> shared_ptr(const shared_ptr<_Ty2>& _Other, const _Const_tag& _Tag) //传入shared_ptr对象来构造,第二个参数指定使用_Const_tag转换
     template<class _Ty2> shared_ptr(const shared_ptr<_Ty2>& _Other, const _Dynamic_tag& _Tag) 传入shared_ptr对象来构造,第二个参数指定使用Dynamic_tag转换
    

    以上构造函数均为拷贝构造函数:均调用_Ptr_base中的_Reset函数,即用现有的对象来构造新的对象,共享资源和计数器,且构造完成后强引用计数+1

    移动构造函数

    template<class _Ty2> shared_ptr(auto_ptr<_Ty2>&& _Other)  //传入auto_ptr临时对象,构造完成后,临时对象销毁
    shared_ptr(_Myt&& _Right) _NOEXCEPT  //传入shared_ptr临时对象,构造完成后,临时对象销毁
    template<class _Ty2, class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,void>::type> shared_ptr(shared_ptr<_Ty2>&& _Right) _NOEXCEPT  //传入不同类型的shared_ptr临时对象,构造完成后,临时对象销毁
    template<class _Ux,class _Dx>	shared_ptr(unique_ptr<_Ux, _Dx>&& _Right) 传入unique_ptr临时对象,获取其资源指针以及删除器,并将_Right的资源指针设置为NULL
    

    以上构造函数均为移动构造函数:用一个临时对象来构造新的对象,继承其资源和计数器,构造完成销毁临时对象,故引用计数不变

    赋值函数

    template<class _Ux,class _Dx> _Myt& operator=(unique_ptr<_Ux, _Dx>&& _Right)  //传入unique_ptr临时对象,赋值给当前shared_ptr对象,_Right的引用计数不变,自身的引用计数-1
    _Myt& operator=(_Myt&& _Right) _NOEXCEPT  //传入shared_ptr临时对象,赋值完成后,_Right的引用计数不变,当前对象的引用计数-1
    template<class _Ty2> _Myt& operator=(shared_ptr<_Ty2>&& _Right) _NOEXCEPT  //传入不同类型的shared_ptr临时对象,赋值完成后,临时对象销毁
    _Myt& operator=(const _Myt& _Right) _NOEXCEPT  //传入shared_ptr对象,可以是临时对象也可以是非临时对象,_Right的引用计数+1,当前对象的引用计数-1
    template<class _Ty2> _Myt& operator=(const shared_ptr<_Ty2>& _Right) _NOEXCEPT  //传入不同类型的shared_ptr对象,_Right的引用计数+1,当前对象的引用计数-1
    template<class _Ty2> _Myt& operator=(auto_ptr<_Ty2>&& _Right)  //传入不同类型的auto_ptr对象,_Right的引用计数不变,当前对象的计数器引用计数-1
    

    由上述赋值函数可知,若为移动赋值函数,传入的对象为临时对象,赋值完成后,临时对象持有资源的引用计数不发生不变化(移动对象std::move),当前对象持有资源的引用计数-1;若为拷贝赋值函数,赋值完成后,传入对象的引用计数+1,当前对象持有资源的引用计数-1

    析构函数

    ~shared_ptr() _NOEXCEPT
    {	// release resource
    	this->_Decref(); //如果引用计数为0,则在计数器类中进行资源释放
    }
    

    某个shared_ptr生命期结束时,会自动调用析构函数,析构函数中会调用计数器的_Decref()函数,资源的强引用计数-1,若强引用计数为0,就会调用_Destroy() 函数释放资源。

    综上所述,智能指针shared_ptr的原理为:所有shared_ptr对象中通过同一个计数器来计算资源的引用计数_Uses,可通过拷贝构造函数、移动构造函数、赋值函数来增加新的shared_ptr指向该对象,并自动调用计数器递增引用计数。当某个shared_ptr生命期结束时,会自动调用析构函数,析构函数中会递减它所指向对象的引用计数,若强引用计数为0,析构函数就会调用计数器的_Destroy() 函数释放内存资源。

    shared_ptr线程安全

    (1)shared_ptr对象的线程安全: 同一个shared_ptr对象被多个线程写不是线程安全的,需要加锁;
    (2)计数器的线程安全: 共享引用计数的不同的shared_ptr对象,其引用计数的增加或减少被多个线程写是线程安全的,因为引用计数的增加或减小是原子操作。

    shared_ptr应用场景

    (1)多个对象共享同一个资源,对象指向资源的创建与销毁是分离的;
    (2)容器中存储动态对象。 假设程序中定义一个容器为vector<int*> v;int * p=new int(4);v.push_back( p);,当程序结束对应容器的生命期也结束时,vector容器会发生析构从而释放其中的元素p,但是并不会释放p所指向的内存资源,就会造成内存泄露。当将容器中的指针元素换为shared_ptr时,即vector<shared_ptr< int>>,当vector生命期结束时,析构容器中的元素,而shared_ptr对象可以自动释放其管理的内存资源,就不会发生内存泄露。
    (3)管理动态数组。

    4、weak_ptr

    weak_ptr也是基类_Ptr_base的派生类,是用户生成弱共享智能指针的接口。weak_ptr的定义比shared_ptr简单很多。

    weak_ptr的构造函数、赋值函数与shared_ptr类似,但是只能通过其它weak_ptr、shared_ptr来构造,在此不再重复。

    weak_ptr中没有重载->操作符,无法获取资源指针,无法访问资源的内存空间,只能判断资源是否有效;

    weak_ptr对象与shared_ptr对象共享一个计数器对象,计数器对象在构造第一个shared_ptr对象时生成;

    weak_ptr利用expired函数检查资源是否有效,若返回true(即引用计数为0),表示资源已经释放,否则,至少有一个shared_ptr对象持有资源。

    weak_ptr不能直接访问资源,而必须调用lock函数检查资源是否被释放,并返回一个shared_ptr对象。若资源已被释放(即expired为true),返回的是一个空shared_ptr对象;否则,返回一个shared_tr,引用计数+1。

    同shared_ptr一样,weak_ptr的生命期结束时,会自动调用析构函数,析构函数中会调用计数器的_Decwref()函数,资源的弱引用计数-1,若弱引用计数为0,就会调用_Delete_this() 函数删除计数器对象。

    综上所述,智能指针weak_ptr的原理为:weak_ptr对象依赖shared_ptr/weak_ptr对象生成,并自动调用计数器递增弱引用计数。当某个weak_ptr生命期结束时,会自动调用析构函数,析构函数中会通过计数器递减弱引用计数,若弱引用计数为0,析构函数就会调用计数器的_Delete_this()函数删除计数器对象。

    不知道大家有没有注意到一个问题,为什么在计数器初始化的时候就要将弱引用计数设置为1呢?
    若弱引用计数初始化为0,在强引用计数不为0的情况下,weak_ptr对象生命期都结束时,此时弱引用计数为0,就会删除计数器,但这时share_ptr对象尚在使用、资源也未释放,就会出现内存错误。

    5、shared_ptr使用注意事项

    在使用shared_ptr指针的过程中,一定要注意避免智能指针的循环引用从而导致的内存泄露,而解决这个问题的方法就是在可能出现循环引用的地方使用weak_ptr来替代shared_ptr。
    举例说明:(以下内容来自博客:关于shared_ptr与weak_ptr的使用。)

    #include <iostream>
    #include <boost/smart_ptr.hpp>
    using namespace std;
    using namespace boost;
    
    class BB;
    class AA
    {
    public:
        AA() { cout << "AA::AA() called" << endl; }
        ~AA() { cout << "AA::~AA() called" << endl; }
        shared_ptr<BB> m_bb_ptr;  //!
    };
    
    class BB
    {
    public:
        BB() { cout << "BB::BB() called" << endl; }
        ~BB() { cout << "BB::~BB() called" << endl; }
        shared_ptr<AA> m_aa_ptr; //!
    };
    
    int main()
    {
        shared_ptr<AA> ptr_a (new AA);
        shared_ptr<BB> ptr_b ( new BB);
        cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
        cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
        //下面两句导致了AA与BB的循环引用,结果就是AA和BB对象都不会析构
        ptr_a->m_bb_ptr = ptr_b;
        ptr_b->m_aa_ptr = ptr_a;
        cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
        cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
    }
    

    运行结果:
    在这里插入图片描述
    由结果可知:由于类A和B中内部的成员变量shared_ptr各自保存了对方的一次引用,使得shared_ptr对象ptr_a和ptr_b各自的引用计数均为2,程序结束时两者的引用计数均-1但都不为0,因此不会释放各自持有的内存资源,即A和B的析构函数不会被调用,因此就发生了内存泄露。

    出现循环引用的解决办法就是将其中一个shared_ptr改为weak_ptr,对应代码如下:

    #include <iostream>
    #include <boost/smart_ptr.hpp>
    using namespace std;
    using namespace boost;
    
    class BB;
    class AA
    {
    public:
        AA() { cout << "AA::AA() called" << endl; }
        ~AA() { cout << "AA::~AA() called" << endl; }
        weak_ptr<BB> m_bb_ptr;  //!
    };
    
    class BB
    {
    public:
        BB() { cout << "BB::BB() called" << endl; }
        ~BB() { cout << "BB::~BB() called" << endl; }
        shared_ptr<AA> m_aa_ptr; //!
    };
    
    int main()
    {
        shared_ptr<AA> ptr_a (new AA);
        shared_ptr<BB> ptr_b ( new BB);
        cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
        cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
        //下面两句导致了AA与BB的循环引用,结果就是AA和BB对象都不会析构
        ptr_a->m_bb_ptr = ptr_b;
        ptr_b->m_aa_ptr = ptr_a;
        cout << "ptr_a use_count: " << ptr_a.use_count() << endl;
        cout << "ptr_b use_count: " << ptr_b.use_count() << endl;
    }
    

    运行结果:
    在这里插入图片描述
    从结果可以看到ptr_a的引用计数为2,而ptr_b的引用计数为1,这是因为weak_ptr不会改变强引用计数,因此在程序结束时ptr_a与ptr_b的引用计数均会-1,此时ptr_b的引用计数变为0,就会释放其持有的内存资源即BB发生析构,而BB析构时又会释放其成员变量m_aa_ptr就会使ptr_a的引用计数-1变为0,从而ptr_a就会释放其持有的资源,即AA发生析构。由此可见,此时不会发生内存泄露。

    参考博客:share_ptr与weak_ptr的区别与联系

    展开全文
  • C++智能指针 shared_ptrweak_ptr 原理

    千次阅读 2017-12-12 15:46:56
    注:源代码摘自 GNU C++,除此之外为原创,转载请注明出处。 ...// // This file is part of the GNU ISO C++ Library. 一、weak_ptr 的 lock() 函数原理/* 当每次有新的 shared_ptr 生成时,会增加 _Sp_
    • 注:源代码摘自 GNU C++,除此之外为原创,转载请注明出处。

    欢迎关注 [懒人漫说] 公众号,分享Java、Android、C/C++ 技术,
    包括基础、自己遇到的问题解决过程。
    在这里插入图片描述
    当然如果关注并留言问题的话,我们力所能及的话会帮你解决并回复哟。我们和你一样,是正在成长的程序员,我们也会分享自己的成长路上的感想,希望可以和你一起努力成长。

    // Copyright (C) 2007-2016 Free Software Foundation, Inc.
    //
    // This file is part of the GNU ISO C++ Library. 
    

    一、weak_ptr 的 lock() 函数原理

    /*  当每次有新的 shared_ptr 生成时,会增加 _Sp_counted_base 的 _M_use_count (+1);
    	当每次有新的 weak_ptr 生成时,会增加 _Sp_counted_base 的 _M_weak_count (+1);
    	通过weak_ptr<x>::lock()函数可以获取x对象的强引用(shared_ptr)。
    	对应的,shared_ptr 析构时,会调用 _Sp_counted_base 的 _M_release 来使 _M_use_count (-1);
    	weak_ptr 析构时,会调用 _Sp_counted_base 的 _M_release 来使 _M_weak_count (-1);
    	当 _M_use_count 的数量为 0 的时候 就会释放,原始的对象(用户自定义对象) 的内存,但是不会释放 
    	_Sp_counted_base 的内存。
    	当  _M_use_count 和 _M_weak_count 都为 0的时候, 才会释放 _Sp_counted_base 的内存。
    	所以将一个普通指针赋值给两个不同的shared_ptr对象会引发double free。
    	eg: 
    		int *n = new int(2);
    		shared_ptr<int> pn1(n);
    		shared_ptr<int> pn2(n);
    		// pn1 和 pn2 内部保存的指针都是n,而且内部引用计数都为1,所以在离开作用域的时候两个指针都会发生析构并释放指向的内存n。
    		尽量使用 shared_ptr<int> pn = make_shared<int> (2); 这种形式初始化一个shared_ptr指针。
    	*/
    /*
     *    此处引用 《Linux 多线程 服务端编程 使用 muduo C++ 网络库》 中对这两个智能指针的描述:
     *      1 shared_ptr 控制对象的生命期。shared_ptr 是强引用,只要有一个指向x对象的shared_ptr存在,该x对象就不会
     *   析构。当指向对象x的最后一个shared_ptr析构或reset()的时候,x保证会被销毁。
     *      2 weak_ptr 不控制对象的生命期,但是它知道对象是否还活着。如果对象还活着,那么它可以提升(promote)为有效的
     *   shared_ptr; 如果对象已经死了,提升会失败,返回一个空的shared_ptr。“提升/lock()” 行为是线程安全的。
     *      3 shared_ptr/weak_ptr 的“计数”在主流平台上是原子操作,没有用锁,性能不俗。
     *      4 shared_ptr/weak_ptr 的线程安全级别与 std::string和STL容器一样。
    */
    	
    	// __shared_count的构造函数会 new 一个 计数对象(_Sp_counted_base),但是__weak_count的构造函数不会new。
    	__shared_count(_Ptr __p) : _M_pi(0)
    	{
    		__try {
    			typedef typename std::tr1::remove_pointer<_Ptr>::type _Tp;
    			_M_pi = new _Sp_counted_base_impl<_Ptr, _Sp_deleter<_Tp>, _Lp>(
    				__p, _Sp_deleter<_Tp>());
    				
    		} __catch(...) {
    			delete __p;
    			__throw_exception_again;
    		}
    	}
    
    	// lock 函数
    	__shared_ptr<_Tp, _Lp> lock() const // never throws
    		{
    	#ifdef __GTHREADS
    			// Optimization: avoid throw overhead.
    			if (expired())
    				return __shared_ptr<element_type, _lp = "">();
    	
    			__try {
    				return __shared_ptr<element_type, _lp = "">(*this);
    				
    			} __catch(const bad_weak_ptr&) {
    				return __shared_ptr<element_type, _lp = "">();
    			}
    	
    	#else
    			// Optimization: avoid try/catch overhead when single threaded.
    			return expired() ? __shared_ptr<element_type, _lp = "">()
    				: __shared_ptr<element_type, _lp = "">(*this);
    	
    	#endif
    		} // XXX MT
    	
    	bool  expired() const // never throws
    	{
    			return _M_refcount._M_get_use_count() == 0;
    	}
    

    二、类成员图:
    这里写图片描述

    三、下面源码有点长,不差资源分的话可以点击链接下载。
    *注:所有的源码参看连接: http://download.csdn.net/download/u013005025/10155393

    四、源码 (//version: Copyright © 2007-2016 Free Software Foundation, Inc.)

    1 weak_ptr 源码
    
    // weak_ptr
    template<typename _tp = "">
    class weak_ptr
    	: public __weak_ptr < _Tp >
    {
    public:
    	weak_ptr()
    		: __weak_ptr<_Tp>() { }
    
    	template<typename _tp1 = "">
    	weak_ptr(const weak_ptr<_Tp1>& __r)
    		: __weak_ptr<_Tp>(__r) { }
    
    	template<typename _tp1 = "">
    	weak_ptr(const shared_ptr<_Tp1>& __r)
    		: __weak_ptr<_Tp>(__r) { }
    
    	template<typename _tp1 = "">
    	weak_ptr&
    		operator=(const weak_ptr<_Tp1>& __r) // never throws
    	{
    		this->__weak_ptr<_Tp>::operator=(__r);
    		return *this;
    	}
    
    	template<typename _tp1 = "">
    	weak_ptr& operator=(const shared_ptr<_Tp1>& __r) // never throws
    	{
    		this->__weak_ptr<_Tp>::operator=(__r);
    		return *this;
    	}
    
    	shared_ptr<_Tp>	lock() const // never throws
    	{
    #ifdef __GTHREADS
    		if (this->expired())
    			return shared_ptr<_Tp>();
    
    		__try{
    			return shared_ptr<_Tp>(*this);
    			
    		}__catch(const bad_weak_ptr&){
    			return shared_ptr<_Tp>();
    		}
    #else
    		return this->expired() ? shared_ptr<_Tp>()
    			: shared_ptr<_Tp>(*this);
    #endif
    	}
    };
    
    2  __weak_ptr 源码
    
    template<typename _lock_policy = "" _lp = "">
    class __weak_ptr
    {
    public:
    	typedef _Tp element_type;
    
    	__weak_ptr() : _M_ptr(0), _M_refcount() // never throws
    	{ }
    	
    	template<typename _tp1 = "">
    	__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
    		: _M_refcount(__r._M_refcount) // never throws
    	{
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    			_M_ptr = __r.lock().get();
    	}
    
    	template<typename _tp1 = "">
    	__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
    		: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
    	{
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    	}
    
    	template<typename _tp1 = "">
    	__weak_ptr& operator=(const __weak_ptr<_Tp1, _Lp>& __r) // never throws
    	{
    		_M_ptr = __r.lock().get();
    		_M_refcount = __r._M_refcount;
    		return *this;
    	}
    
    	template<typename _tp1 = "">
    	__weak_ptr& operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
    	{
    		_M_ptr = __r._M_ptr;
    		_M_refcount = __r._M_refcount;
    		return *this;
    	}
    
    	__shared_ptr<_Tp, _Lp> lock() const // never throws
    	{
    #ifdef __GTHREADS
    		// Optimization: avoid throw overhead.
    		if (expired())
    			return __shared_ptr<element_type, _lp = "">();
    
    		__try {
    			return __shared_ptr<element_type, _lp = "">(*this);
    			
    		} __catch(const bad_weak_ptr&) {
    			return __shared_ptr<element_type, _lp = "">();
    		}
    
    #else
    		// Optimization: avoid try/catch overhead when single threaded.
    		return expired() ? __shared_ptr<element_type, _lp = "">()
    			: __shared_ptr<element_type, _lp = "">(*this);
    
    #endif
    	} // XXX MT
    
    	long use_count() const // never throws
    	{
    		return _M_refcount._M_get_use_count();
    	}
    
    	bool expired() const // never throws
    	{
    		return _M_refcount._M_get_use_count() == 0;
    	}
    
    	void reset() // never throws
    	{
    		__weak_ptr().swap(*this);
    	}
    
    	void swap(__weak_ptr& __s) // never throws
    	{
    		std::swap(_M_ptr, __s._M_ptr);
    		_M_refcount._M_swap(__s._M_refcount);
    	}
    
    private:
    	// Used by __enable_shared_from_this.
    	void _M_assign(_Tp* __ptr, const __shared_count<_Lp>& __refcount)
    	{
    		_M_ptr = __ptr;
    		_M_refcount = __refcount;
    	}
    
    	template<typename _tp1 = "">
    	bool _M_less(const __weak_ptr<_Tp1, _Lp>& __rhs) const
    	{
    		return _M_refcount < __rhs._M_refcount;
    	}
    
    	template<typename _lock_policy = "" _lp1 = ""> friend class __shared_ptr;
    	template<typename _lock_policy = "" _lp1 = ""> friend class __weak_ptr;
    	friend class __enable_shared_from_this < _Tp, _Lp > ;
    	friend class enable_shared_from_this < _Tp > ;
    
    	// Friend injected into namespace and found by ADL.
    	template<typename _tp1 = "">
    	friend inline bool
    		operator<(const __weak_ptr& __lhs, const __weak_ptr<_Tp1, _Lp>& __rhs)
    	{
    		return __lhs._M_less(__rhs);
    	}
    
    	_Tp*           _M_ptr;         // Contained pointer.
    	__weak_count<_Lp>  _M_refcount;    // Reference counter.
    };
    
    3 __weak_count 源码
    
    template<_Lock_policy _Lp>
    class __weak_count
    {
    public:
    	__weak_count() : _M_pi(0) // nothrow
    	{ }
    
    	__weak_count(const __shared_count<_Lp>& __r)
    		: _M_pi(__r._M_pi) // nothrow
    	{
    		if (_M_pi != 0)
    			_M_pi->_M_weak_add_ref();
    	}
    
    	__weak_count(const __weak_count<_Lp>& __r)
    		: _M_pi(__r._M_pi) // nothrow
    	{
    		if (_M_pi != 0)
    			_M_pi->_M_weak_add_ref();
    	}
    
    	~__weak_count() // nothrow
    	{
    		if (_M_pi != 0)
    			_M_pi->_M_weak_release();
    	}
    
    	__weak_count<_Lp>& operator=(const __shared_count<_Lp>& __r) // nothrow
    	{
    		_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
    		if (__tmp != 0)
    			__tmp->_M_weak_add_ref();
    		if (_M_pi != 0)
    			_M_pi->_M_weak_release();
    		_M_pi = __tmp;
    		return *this;
    	}
    
    	__weak_count<_Lp>& operator=(const __weak_count<_Lp>& __r) // nothrow
    	{
    		_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
    		if (__tmp != 0)
    			__tmp->_M_weak_add_ref();
    		if (_M_pi != 0)
    			_M_pi->_M_weak_release();
    		_M_pi = __tmp;
    		return *this;
    	}
    
    	void _M_swap(__weak_count<_Lp>& __r) // nothrow
    	{
    		_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
    		__r._M_pi = _M_pi;
    		_M_pi = __tmp;
    	}
    
    	long _M_get_use_count() const // nothrow
    	{
    		return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0;
    	}
    
    	friend inline bool
    		operator==(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
    	{
    		return __a._M_pi == __b._M_pi;
    	}
    
    	friend inline bool
    		operator<(const __weak_count<_Lp>& __a, const __weak_count<_Lp>& __b)
    	{
    		return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi);
    	}
    
    private:
    	friend class __shared_count < _Lp > ;
    
    	_Sp_counted_base<_Lp>*  _M_pi;
    };
    

    五、shared_ptr 源码

    // The actual shared_ptr, with forwarding constructors and
    // assignment operators.
    // shared_ptr
    template<typename _tp = "">
    class shared_ptr
    	: public __shared_ptr < _Tp >
    {
    public:
    	shared_ptr()
    		: __shared_ptr<_Tp>() { }
    
    	template<typename _tp1 = "">
    	explicit
    		shared_ptr(_Tp1* __p)
    		: __shared_ptr<_Tp>(__p) { }
    
    	template<typename _deleter = "" typename = "">
    	shared_ptr(_Tp1* __p, _Deleter __d)
    		: __shared_ptr<_Tp>(__p, __d) { }
    
    	template<typename _tp1 = "">
    	shared_ptr(const shared_ptr<_Tp1>& __r)
    		: __shared_ptr<_Tp>(__r) { }
    
    	template<typename _tp1 = "">
    	explicit
    		shared_ptr(const weak_ptr<_Tp1>& __r)
    		: __shared_ptr<_Tp>(__r) { }
    
    #if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED
    	template<typename _tp1 = "">
    	explicit
    		shared_ptr(std::auto_ptr<_Tp1>& __r)
    		: __shared_ptr<_Tp>(__r) { }
    #endif
    
    	template<typename _tp1 = "">
    	shared_ptr(const shared_ptr<_Tp1>& __r, __static_cast_tag)
    		: __shared_ptr<_Tp>(__r, __static_cast_tag()) { }
    
    	template<typename _tp1 = "">
    	shared_ptr(const shared_ptr<_Tp1>& __r, __const_cast_tag)
    		: __shared_ptr<_Tp>(__r, __const_cast_tag()) { }
    
    	template<typename _tp1 = "">
    	shared_ptr(const shared_ptr<_Tp1>& __r, __dynamic_cast_tag)
    		: __shared_ptr<_Tp>(__r, __dynamic_cast_tag()) { }
    
    	template<typename _tp1 = "">
    	shared_ptr& operator=(const shared_ptr<_Tp1>& __r) // never throws
    	{
    		this->__shared_ptr<_Tp>::operator=(__r);
    		return *this;
    	}
    
    #if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED
    	template<typename _tp1 = "">
    	shared_ptr& operator=(std::auto_ptr<_Tp1>& __r)
    	{
    		this->__shared_ptr<_Tp>::operator=(__r);
    		return *this;
    	}
    #endif
    };
    
    // __shared_ptr
    struct __static_cast_tag { };
    struct __const_cast_tag { };
    struct __dynamic_cast_tag { };
    // A smart pointer with reference-counted copy semantics.  The
    // object pointed to is deleted when the last shared_ptr pointing to
    // it is destroyed or reset.
    template<typename _lock_policy = "" _lp = "">
    class __shared_ptr
    {
    public:
    	typedef _Tp   element_type;
    
    	__shared_ptr()
    		: _M_ptr(0), _M_refcount() // never throws
    	{ }
    
    	template<typename _tp1 = "">
    	explicit __shared_ptr(_Tp1* __p)
    		: _M_ptr(__p), _M_refcount(__p)
    	{
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    			typedef int _IsComplete[sizeof(_Tp1)];
    		__enable_shared_from_this_helper(_M_refcount, __p, __p);
    	}
    
    	template<typename _deleter = "" typename = "">
    	__shared_ptr(_Tp1* __p, _Deleter __d)
    		: _M_ptr(__p), _M_refcount(__p, __d)
    	{
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    			// TODO requires _Deleter CopyConstructible and __d(__p) well-formed
    			__enable_shared_from_this_helper(_M_refcount, __p, __p);
    	}
    
    	//  generated copy constructor, assignment, destructor are fine.
    
    	template<typename _tp1 = "">
    	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r)
    		: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount) // never throws
    	{
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    	}
    
    	template<typename _tp1 = "">
    	explicit
    		__shared_ptr(const __weak_ptr<_Tp1, _Lp>& __r)
    		: _M_refcount(__r._M_refcount) // may throw
    	{
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    			// It is now safe to copy __r._M_ptr, as _M_refcount(__r._M_refcount)
    			// did not throw.
    			_M_ptr = __r._M_ptr;
    	}
    
    #if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED
    	// Postcondition: use_count() == 1 and __r.get() == 0
    	template<typename _tp1 = "">
    	explicit __shared_ptr(std::auto_ptr<_Tp1>& __r)
    		: _M_ptr(__r.get()), _M_refcount()
    	{ // TODO requries delete __r.release() well-formed
    		__glibcxx_function_requires(_ConvertibleConcept<_Tp1*, _Tp*>)
    			typedef int _IsComplete[sizeof(_Tp1)];
    		_Tp1* __tmp = __r.get();
    		_M_refcount = __shared_count<_Lp>(__r);
    		__enable_shared_from_this_helper(_M_refcount, __tmp, __tmp);
    	}
    
    #endif
    
    	template<typename _tp1 = "">
    	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __static_cast_tag)
    		: _M_ptr(static_cast<element_type*>(__r._M_ptr)),
    		_M_refcount(__r._M_refcount)
    	{ }
    
    	template<typename _tp1 = "">
    	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __const_cast_tag)
    		: _M_ptr(const_cast<element_type*>(__r._M_ptr)),
    		_M_refcount(__r._M_refcount)
    	{ }
    
    	template<typename _tp1 = "">
    	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r, __dynamic_cast_tag)
    		: _M_ptr(dynamic_cast<element_type*>(__r._M_ptr)),
    		_M_refcount(__r._M_refcount)
    	{
    		if (_M_ptr == 0) // need to allocate new counter -- the cast failed
    			_M_refcount = __shared_count<_Lp>();
    	}
    
    	template<typename _tp1 = "">
    	__shared_ptr& operator=(const __shared_ptr<_Tp1, _Lp>& __r) // never throws
    	{
    		_M_ptr = __r._M_ptr;
    		_M_refcount = __r._M_refcount; // __shared_count::op= doesn't throw
    		return *this;
    	}
    
    #if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED
    	template<typename _tp1 = "">
    	__shared_ptr& operator=(std::auto_ptr<_Tp1>& __r)
    	{
    		__shared_ptr(__r).swap(*this);
    		return *this;
    	}
    #endif
    
    	void reset() // never throws
    	{
    		__shared_ptr().swap(*this);
    	}
    
    	template<typename _tp1 = "">
    	void reset(_Tp1* __p) // _Tp1 must be complete.
    	{
    		// Catch self-reset errors.
    		_GLIBCXX_DEBUG_ASSERT(__p == 0 || __p != _M_ptr);
    		__shared_ptr(__p).swap(*this);
    	}
    
    	template<typename _deleter = "" typename = "">
    	void reset(_Tp1* __p, _Deleter __d)
    	{
    		__shared_ptr(__p, __d).swap(*this);
    	}
    
    	// Allow class instantiation when _Tp is [cv-qual] void.
    	typename std::tr1::add_reference<_Tp>::type
    		operator*() const // never throws
    	{
    		_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
    		return *_M_ptr;
    	}
    
    	_Tp* operator->() const // never throws
    	{
    		_GLIBCXX_DEBUG_ASSERT(_M_ptr != 0);
    		return _M_ptr;
    	}
    
    	_Tp* get() const // never throws
    	{
    		return _M_ptr;
    	}
    
    	// Implicit conversion to "bool"
    private:
    	typedef _Tp* __shared_ptr::*__unspecified_bool_type;
    
    public:
    	operator __unspecified_bool_type() const // never throws
    	{
    		return _M_ptr == 0 ? 0 : &__shared_ptr::_M_ptr;
    	}
    
    	bool unique() const // never throws
    	{
    		return _M_refcount._M_unique();
    	}
    
    	long use_count() const // never throws
    	{
    		return _M_refcount._M_get_use_count();
    	}
    
    	void swap(__shared_ptr<_Tp, _Lp>& __other) // never throws
    	{
    		std::swap(_M_ptr, __other._M_ptr);
    		_M_refcount._M_swap(__other._M_refcount);
    	}
    
    private:
    	void* _M_get_deleter(const std::type_info& __ti) const
    	{
    		return _M_refcount._M_get_deleter(__ti);
    	}
    
    	template<typename _lock_policy = "" _lp1 = "">
    	bool _M_less(const __shared_ptr<_Tp1, _Lp1>& __rhs) const
    	{
    		return _M_refcount < __rhs._M_refcount;
    	}
    
    	template<typename _lock_policy = "" _lp1 = ""> friend class __shared_ptr;
    	template<typename _lock_policy = "" _lp1 = ""> friend class __weak_ptr;
    
    	template<typename _lock_policy = "" _lp1 = "" typename = "">
    	friend _Del* get_deleter(const __shared_ptr<_Tp1, _Lp1>&);
    
    	// Friends injected into enclosing namespace and found by ADL:
    	template<typename _tp1 = "">
    	friend inline bool
    		operator==(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
    	{
    		return __a.get() == __b.get();
    	}
    
    	template<typename _tp1 = "">
    	friend inline bool
    		operator!=(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
    	{
    		return __a.get() != __b.get();
    	}
    
    	template<typename _tp1 = "">
    	friend inline bool
    		operator<(const __shared_ptr& __a, const __shared_ptr<_Tp1, _Lp>& __b)
    	{
    		return __a._M_less(__b);
    	}
    
    	_Tp*             _M_ptr;         // Contained pointer.
    	__shared_count<_Lp>  _M_refcount;    // Reference counter.
    };
    
    
    // __shared_count
    template<_Lock_policy _Lp = __default_lock_policy>
    class __shared_count
    {
    public:
    	__shared_count()
    		: _M_pi(0) // nothrow
    	{ }
    
    	template<typename _ptr = "">
    	__shared_count(_Ptr __p) : _M_pi(0)
    	{
    		__try
    		{
    			typedef typename std::tr1::remove_pointer<_Ptr>::type _Tp;
    			_M_pi = new _Sp_counted_base_impl<_Ptr, _Sp_deleter<_Tp>, _Lp>(
    				__p, _Sp_deleter<_Tp>());
    		}
    		__catch(...)
    		{
    			delete __p;
    			__throw_exception_again;
    		}
    	}
    
    	template<typename _deleter = "" typename = "">
    	__shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
    	{
    		__try
    		{
    			_M_pi = new _Sp_counted_base_impl<_Ptr, _Deleter, _Lp>(__p, __d);
    		}
    		__catch(...)
    		{
    			__d(__p); // Call _Deleter on __p.
    			__throw_exception_again;
    		}
    	}
    
    	// Special case for auto_ptr<_Tp> to provide the strong guarantee.
    	template<typename _tp = "">
    	explicit
    		__shared_count(std::auto_ptr<_Tp>& __r)
    		: _M_pi(new _Sp_counted_base_impl < _Tp*,
    		_Sp_deleter<_Tp>, _Lp > (__r.get(), _Sp_deleter<_Tp>()))
    	{
    		__r.release();
    	}
    
    	// Throw bad_weak_ptr when __r._M_get_use_count() == 0.
    	explicit __shared_count(const __weak_count<_Lp>& __r);
    
    	~__shared_count() // nothrow
    	{
    		if (_M_pi != 0)
    			_M_pi->_M_release();
    	}
    
    	__shared_count(const __shared_count& __r)
    		: _M_pi(__r._M_pi) // nothrow
    	{
    		if (_M_pi != 0)
    			_M_pi->_M_add_ref_copy();
    	}
    
    	__shared_count& operator=(const __shared_count& __r) // nothrow
    	{
    		_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
    		if (__tmp != _M_pi)
    		{
    			if (__tmp != 0)
    				__tmp->_M_add_ref_copy();
    			if (_M_pi != 0)
    				_M_pi->_M_release();
    			_M_pi = __tmp;
    		}
    		return *this;
    	}
    
    	void _M_swap(__shared_count& __r) // nothrow
    	{
    		_Sp_counted_base<_Lp>* __tmp = __r._M_pi;
    		__r._M_pi = _M_pi;
    		_M_pi = __tmp;
    	}
    
    	long _M_get_use_count() const // nothrow
    	{
    		return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0;
    	}
    
    	bool _M_unique() const // nothrow
    	{
    		return this->_M_get_use_count() == 1;
    	}
    
    	friend inline bool
    		operator==(const __shared_count& __a, const __shared_count& __b)
    	{
    		return __a._M_pi == __b._M_pi;
    	}
    
    	friend inline bool
    		operator<(const __shared_count& __a, const __shared_count& __b)
    	{
    		return std::less<_Sp_counted_base<_Lp>*>()(__a._M_pi, __b._M_pi);
    	}
    
    	void* _M_get_deleter(const std::type_info& __ti) const
    	{
    		return _M_pi ? _M_pi->_M_get_deleter(__ti) : 0;
    	}
    
    private:
    	friend class __weak_count < _Lp > ;
    
    	_Sp_counted_base<_Lp>*  _M_pi;
    };
    
    // _Sp_counted_base
    template<_Lock_policy _Lp = __default_lock_policy>
    class _Sp_counted_base
    	: public _Mutex_base < _Lp >
    {
    public:
    	_Sp_counted_base()
    		: _M_use_count(1), _M_weak_count(1) { }
    
    	virtual	~_Sp_counted_base() // nothrow 
    	{ }
    
    	// Called when _M_use_count drops to zero, to release the resources
    	// managed by *this.
    	virtual void _M_dispose() = 0; // nothrow
    
    	// Called when _M_weak_count drops to zero.
    	virtual void _M_destroy() // nothrow
    	{
    		delete this;
    	}
    
    	virtual void* _M_get_deleter(const std::type_info&) = 0;
    
    	void _M_add_ref_copy()
    	{
    		__gnu_cxx::__atomic_add_dispatch(&_M_use_count, 1);
    	}
    
    	void _M_add_ref_lock();
    
    	void _M_release() // nothrow
    	{
    		// Be race-detector-friendly.  For more info see bits/c++config.
    		_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_use_count);
    		if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, -1) == 1)
    		{
    			_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_use_count);
    			_M_dispose();
    			// There must be a memory barrier between dispose() and destroy()
    			// to ensure that the effects of dispose() are observed in the
    			// thread that runs destroy().
    			// See https://gcc.gnu.org/ml/libstdc++/2005-11/msg00136.html
    			if (_Mutex_base<_Lp>::_S_need_barriers)
    			{
    				__atomic_thread_fence(__ATOMIC_ACQ_REL);
    			}
    
    			// Be race-detector-friendly.  For more info see bits/c++config.
    			_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
    			if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count,
    				-1) == 1)
    			{
    				_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
    				_M_destroy();
    			}
    		}
    	}
    
    	void _M_weak_add_ref() // nothrow
    	{
    		__gnu_cxx::__atomic_add_dispatch(&_M_weak_count, 1);
    	}
    
    	void _M_weak_release() // nothrow
    	{
    		// Be race-detector-friendly. For more info see bits/c++config.
    		_GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_weak_count);
    		if (__gnu_cxx::__exchange_and_add_dispatch(&_M_weak_count, -1) == 1)
    		{
    			_GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_weak_count);
    			if (_Mutex_base<_Lp>::_S_need_barriers)
    			{
    				// See _M_release(),
    				// destroy() must observe results of dispose()
    				__atomic_thread_fence(__ATOMIC_ACQ_REL);
    			}
    			_M_destroy();
    		}
    	}
    
    	long _M_get_use_count() const // nothrow
    	{
    		// No memory barrier is used here so there is no synchronization
    		// with other threads.
    		return const_cast<const volatile = "">(_M_use_count);
    	}
    
    private:
    	_Sp_counted_base(_Sp_counted_base const&);
    	_Sp_counted_base& operator=(_Sp_counted_base const&);
    
    	_Atomic_word  _M_use_count;     // #shared
    	_Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
    };
    

    End ----------------------------------------------------------------------------------------------------

    展开全文
  • 本文记录自己对智能指针的理解,主要涉及shared_ptr,unique_ptr,weak_ptr三个常用的智能指针的引用,原理,遇到的问题展开。
  • #ifndef __SHARED_PTR_ #define __SHARED_PTR_ template <typename T> class shared_ptr { public: shared_ptr(T* p) : count(new int(1)), _ptr(p) {} shared_ptr(shared_ptr<T>& other) : ...
  • shared_ptr C++程序设计中使用堆内存是非常频繁的操作,堆内存的申请和释放都由程序员自己管理。...C++里面的四个智能指针: auto_ptr, unique_ptr,shared_ptr, weak_ptr 其中后三个是C++11支持, 并且第一个已
  • 智能指针(三):weak_ptr浅析

    万次阅读 多人点赞 2018-09-01 14:36:26
    weak_ptr这个指针天生一副“小弟”的模样,也是在C++11的时候引入的标准库,它的出现完全是为了弥补它老大shared_ptr天生有缺陷的问题,其实相比于上一代的智能指针auto_ptr来说,新进老大shared_ptr可以说近乎完美...
  • shared_ptr 继承体系和关键成员 由下图可知,一个shared_ptr对象,里面其实包含两个指针,一个指针指向被管理对象(manged object),一个指向管理对象(manager object),其中管理对象(manager object)中也包含...
  • 但可以用在函数返回值中 unique_ptr可做为容器元素 用unique_ptr传递删除器 5 weak_ptr原理 6 auto_ptr(C++11已放弃) 7 总结及源码位置 boost::scoped_ptr 参考: 参考资料:《C++ Primer中文版 第五版》 1 介绍...
  • 智能指针:auto_ptr、unique_ptr、shared_ptrweak_ptr
  • 【C++】weak_ptr弱引用智能指针详解

    千次阅读 多人点赞 2020-05-03 15:34:11
    相比于上一代的智能指针auto_ptr来说,新进老大shared_ptr可以说近乎完美,但是通过引用计数实现的它,虽然解决了指针独占的问题,但也引来了引用成环的问题,这种问题靠它自己是没办法解决的,所以在C++11的时候将...
  • C++中的智能指针实现是通过一个类来管理实际上的指针,这个类要具备指针的基本操作。 shared_ptr 创建一个智能指针 std::shared_ptr<int> ptra = std::make_shared<int>(20); std::shared_ptr<int&...
  • 三种智能指针 shared_ptr,unique_ptrweak_ptr; 将shared_ptr存放在一个容器中,不再需要它的时候,要erase掉。 allocator负责封装堆内存管理的对象,它们在整个标准库中使用,特别是STL容器使用它们来管理容器...
  • C++智能指针、shared_ptr、unique_ptrweak_ptr详解
  • c++最开始设计没有考虑gc(garbage collection...shared_ptr原理是引用计数,用于指针需要被传递复制的时候 weak_ptr主要就是为了配合shared_ptr防止出现循环引用(两个对象各持有各自的shared_ptr, 都无法先释放), ...
  • 一、class shared_ptr shared_ptr具有共享式拥有的概念。即多个shared_ptr可以指向相同的对象,该对象和其相关资源会在“最后一个引用被销毁”时释放。 1、shared_ptr的初始化: (1)直接使用初始化 shared_...
  • 从源码看std::weak_ptr

    2022-06-25 09:41:31
    weak_ptr
  • 为什么要使用shared_ptr3.shared_ptr的使用1.shared_ptr原理2.shared_ptr的使用 1.往期回顾 2.为什么要使用shared_ptr 这是因为,无论是auto_ptr还是unique_ptr都是排它型的,即只允许一个智能指针对象引用控制一块...
  • weak_ptr引入可以解决shared_ptr交叉引用时无法释放资源的问题。 示例代码: #include <iostream> #include <memory> using namespace std; class B; class A{ public: A(){cout << "A ...
  • C++智能指针weak_ptr详解

    千次阅读 2020-07-30 22:18:55
    但是通过引用计数实现的它,虽然解决了指针独占的问题,但也引来了引用成环的问题,这种问题靠它自己是没办法解决的,所以在C++11的时候将shared_ptrweak_ptr一起引入了标准库,用来解决循环引用的问题。...
  • 三种智能指针:shared_ptr、unique_ptrweak_ptr,均定义在memory头文件中。 1、shared_ptr 定义: shared_ptr允许多个对象指向同一个对象,是一个标准的共享所有权的智能指针,C++11引入到C++ STL 用法:
  • #include <iostream> #include <vector> #include <memory> using namespace std;... 标准库还定义了一种名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象...
  • C++11智能指针(unique_ptr、shared_ptrweak_ptr)

    千次阅读 多人点赞 2019-07-11 23:31:15
    更多文章欢迎访问 程序员小非 博客 很多人怕写C/C++ 程序就是因为指针,因为指针给了程序员高度的自由,同样也赋予了高度的责任,稍有不慎就...C++ 11中定义了unique_ptr、shared_ptrweak_ptr三种智能指针(smart ...
  • 在正式介绍weak_ptr之前,我们先来回忆一下shard_ptr的一些知识,我们直到shared_ptr是采用引用计数的智能指针,多个shared_ptr实例可以指向同一个对象,并维护了一个共享的引用计数器。 深入 weak_ptr也是一个引用...
  • 1. auto_ptr auto_ptr主要是用来解决资源自动释放的问题,比如如下代码: void Function() { Obj*p = new Obj(20); ... if (error occor) throw ... 或者 retrun; delete p; } 在函数遇到错误之后,一般会抛异常...
  • C++智能指针3——弱指针weak_ptr详解

    千次阅读 2020-01-30 11:21:04
    共享指针shared_ptr指针存在的一些问题可以有弱指针weak_ptr解决。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,041
精华内容 2,016
关键字:

weak_ptr实现原理