精华内容
下载资源
问答
  • Weak_ptr实现

    2020-04-01 10:58:05
    前言: 循环引用实例: ... @task:shared_ptr循环引用实例 */ #include<bits/stdc++.h> using namespace std; struct node{ shared_ptr<node> t; }; int main(){ shared_ptr<node> a(n...

    前言:

    循环引用实例:

    /*
        @author:wcx
        @task:shared_ptr循环引用实例
    */
    #include<bits/stdc++.h>
    using namespace std;
    struct node{
        shared_ptr<node> t;
    };
    int main(){
        shared_ptr<node> a(new node);
        shared_ptr<node> b(new node);
        a->t=b;
        b->t=a;
    }
    

    当a删除的时候,因为自身引用计数为2(b指向了自己),所有减为1不会释放内部成员,也就是指向的b引用计数不会变化,释放b的时候也一样,所以到最后两者都不会释放,计数为1。

    解决方法:

    用weak_ptr解决,它是辅助shared_ptr的一个结构,不增加引用计数,准确意义来说它不是个指针,它不能随意指向。

    /*
        @author:wcx
        @task:shared_ptr循环引用解决
    */
    #include<bits/stdc++.h>
    using namespace std;
    struct node{
        weak_ptr<node> t;
    };
    int main(){
        shared_ptr<node> a(new node);
        shared_ptr<node> b(new node);
        a->t=b;
        b->t=a;
    }
    

    Weak_ptr实现:

    /*
        @author:wcx
        @task:weak_ptr实现
    */
    #include<bits/stdc++.h>
    using namespace std;
    namespace P{
        template <typename T>
        class Weak_ptr{
            //不占用引用计数
        public:
            Weak_ptr(const shared_ptr<T> da):s(da.ptr){}
            ~Weak_ptr(){}
        protected:
            T *s;
        };
    }
    int main(){
        using namespace P;
        Shared_ptr<int> a(new int);
        Weak_ptr<int> t(a);
        return 0;
    }
    
    展开全文
  • C++智能指针: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描述

    声明

    头文件:<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

    展开全文
  • Shared_ptr采用引用计数实现自动化资源管理,当引用计数降为0时,对象(资源)即被销毁。weak_ptr也是一个引用计数型的智能指针,但是它不增加对象的引用计数,即弱(weak)引用。 Shared_ptr在下列情况之一出现时...

    一、前言

    Shared_ptr采用引用计数实现自动化资源管理,当引用计数降为0时,对象(资源)即被销毁。weak_ptr也是一个引用计数型的智能指针,但是它不增加对象的引用计数,即弱(weak)引用。

    Shared_ptr在下列情况之一出现时销毁对象并释放内存:

    1. 最后占有std::shared_ptr对象被销毁时;
    2. 最后占有std::shared_ptr对象被通过operator=或reset()赋值为另一个指针。

    ●shared_ ptr控制对象的生命期。shared_ptr是强引用(想象成用铁丝绑住堆上的对象),只要有一个指向x对象的shared_ptr存在,该x对象就不会析构。当指向对象x的最后-一个shared_ptr 析构或reset()的时候,x保证会被销毁。

    ●weak_ptr不控制对象的生命期,但是它知道对象是否还活着(想象成用棉线轻轻拴住堆上的对象)。如果对象还活着,那么它可以提升( promote)为有效的shared. ptr;如果对象已经死了,提升会失败,返回一个空的shared_ ptr。“提升/1ock()”行为是线程安全的。

    ●shared_ ptr/weak_ ptr的“计数”在主流平台上是原子操作,没有用锁,性能不俗。

    ●shared. _ptr /weak _ptr的线程安全级别与std::string和STL容器一样。

    二、示例代码

    shared_ptr和weak_ptr示例代码。

    代码:

    #include <iostream>
    #include <memory> // 加载该头文件才能使用智能指针
    
    using namespace std;
    
    class 
    展开全文
  • shared_ptr以及weak_ptr实现的弱回调以及对象池管理 直接上代码一条一条的解释 class StockFactory:public boost::enable_shared_from_this,boost::noncopyable { public: shared_ptr get(const string& key) { ...

    shared_ptr以及weak_ptr实现的弱回调以及对象池管理

    直接上代码一条一条的解释

    class StockFactory:public boost::enable_shared_from_this<StockFactory>,boost::noncopyable
    {
    public:
    	shared_ptr<Stock> get(const string& key)
    	{
    		shared_ptr<Stock> pStock;//从工厂中产生的相应股票的shared_ptr,如果这只股票不存在先创建。
    		MutexLockGuard lock(mutex_);
    		weak_ptr<Stock> wkStock=stocks_[key];如果key不存在直接就穿件一个wak_ptr.
    		pStock=wkStock.lock();
    		if(!pStock)
    		{
    			pStock.reset(new Stock(key),boost::bind(&Stock::weakDeteleCallBack,boost::weak_ptr(shared_from_this),_1));//这一句话非常重要,这里实			//现了弱回调,把factory的weak_ptr传入到相应的Stock_类,避免延长了factory的生命期,同时在stock类析构的时候可以判断相应的Factory是否			//还活着
    			wkStock=pStock;
    		}
    		return pStock;
    	}
    private:
    	static void weakDeleteCallback(const boost::weak_ptr<StockFactory>& wkFactory,Stock* stock)
    	{
    		shared_ptr<StockFactory> factory(wkFactory.lock());//尝试提升,看是否还存在Factory
    		if(factory)
    		{
    			fatory->removestock(stock);
    		}
    		delete stock;
    	}
    private:
    	mutable MutexLock mutex_;
    	map<string,weak_ptr<Stock> > stocks_;//一个对象池,使用weak_ptr以避免延长股票类stock的生命期,根据股票号key与相应的对象进行关联。
    }



    展开全文
  • 主要介绍了C++11新特性之智能指针,包括shared_ptr, unique_ptrweak_ptr的基本使用,感兴趣的小伙伴们可以参考一下
  • 关于C++智能指针 weak_ptr (弱引用 智能指针) 和 shared_ptr (强引用 智能指针)的源文件。 资源分不能设为0了。。
  • 考察较多的就是shared_ptr的手写实现了,这里不是源码,只是模拟实现。 template<class T> //模板 class Share_ptr { // weak_ptr的friend friend class Weak_ptr<T>; //这里先不用在意,稍后解释 p
  • weakptr的作为弱引用指针,其实现依赖于counter的计数器类和share_ptr的赋值,构造,所以先把counter和share_ptr简单实现 Counter简单实现 class Counter { public: Counter() : s(0), w(0){}; int s; //share_ptr...
  • c++11 智能指针 unique_ptr shared_ptr weak_ptr 区别

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 15,972
精华内容 6,388
关键字:

weak_ptr实现