`
optman
  • 浏览: 44059 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

对象的强引用和弱引用

阅读更多

如何保证一个对象在释放后不会再被访问? 最简单的是使用带引用计数的智能指针,但是强引用会导致对象不会被释放。那么弱引用如何?弱引用允许对象被释放,弱引用必须先转成强引用才能对对象进行操作,如果转换失败,则表示对象已经被删除。


正好看到一篇文章“当析构函数遇到多线程──C++ 中线程安全的对象回调”,其大意是使用shared_ptr和weak_ptr来完成。对象必须使用shared_ptr来引用,weak_ptr必须先转成shared_ptr才能对对象进行操作。


几个相关的智能指针封装类

auto_ptr   可以自动完成指针的释放。问题是,auto_ptr允许复制,并且内部对象的归属就自动转移到新生成的auto_ptr对象上,现有auto_ptr就不能访问了,这很容易让人困惑和导致错误,也因此auto_ptr不能用于标准STL容器中(因为涉及元素拷贝)。  

scoped_ptr  跟auto_ptr的功能一样,但是不允许被复制,这样就避免了不小心导致的错误。

shared_ptr   跟auto_ptr和scoped_ptr不一样,shared_ptr允许复制,多个shared_ptr实例指向的是同一个内部对象,并通过引用计数来控制内部对象的生命周期。因为可以复制,所以shared_ptr可以用于标准STL容器中。

weak_ptr  跟shared_ptr一样,weak_ptr 也允许复制。但与shared_ptr锁住内部对象的生命周期不一样的是,weak_ptr允许shared_ptr指向的对象被释放。在对内部对象操作前,weak_ptr必须先转成shared_ptr(即先锁住内部对象避免被释放,如果锁定失败则意味着对象已经被释放了)。weak_ptr必须从shared_ptr构造得来,因为需要共享一些数据,要不怎么能转换呢。


要保证对象的析构安全,必须统一通过shared_ptr和weak_ptr来引用对象,不能直接使用裸指针。 现在的问题是如何保证线程安全,特别是从weak_ptr转成shared_ptr的瞬间。

关键是如下操作引用计数的代码,add_ref_lock必须保证在use_count_ 不为零的时候加一成功!代码很精妙。


    bool add_ref_lock() // true on success
    {
        for( ;; )
        {
            long tmp = static_cast< long const volatile& >( use_count_ );
            if( tmp == 0 ) return false;

#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, == 1200 )

            // work around a code generation bug

            long tmp2 = tmp + 1;
            if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp2, tmp ) == tmp2 - 1 ) return true;

#else

            if( BOOST_INTERLOCKED_COMPARE_EXCHANGE( &use_count_, tmp + 1, tmp ) == tmp ) return true;

#endif
        }
    }

    void release() // nothrow
    {
        if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
        {
            dispose();
            weak_release();
        }
    }

分享到:
评论

相关推荐

    Java对象的强、软、弱和虚引用

    在JDK1.2以前的版本中,当一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于可触及状态,程序才能使用它。这 就像在日常生活中,从商店购买了某样物品后,如果有用,就一直保留它,...

    Java理论与实践:用弱引用堵住内存泄漏

    本文介绍了弱引用是对一个对象的引用的持有者。...弱引用和弱集合是对堆进行管理的强大工具,使得应用程序可以使用更复杂的可及性方案,而不只是由普通(强)引用所提供的“要么全部要么没有”可及性。

    Java对象的强、软、弱和虚引用1

    3.2 如果使用软引用SoftReference的特点是它的一个实例保存对一个Java对象的软引用,该软引用的存在不妨碍垃圾收集线程对该Java对象的回收 3.

    Android利用软引用和弱引用避免OOM的方法

    想必很多朋友对OOM(OutOfMemory)这个错误不会陌生,而当遇到这种... 从Java SE2开始,就提供了四种类型的引用:强引用、软引用、弱引用和虚引用。Java中提供这四种引用类型主要有两个目的:第一是可以让程序员通过

    强应用软引用弱引用与垃圾收集的关系1

    (比如新创建一个对象,那么创建它的线程对它就是强可达)\2. 软可达: 只能通过软引用才能访问到对象状态\3. 弱可达: 只能通过弱引用访问时的状态, 十分临近

    Java虚拟机(四)——Java引用对象4种类型

    他们分别是强引用(StrongReference),软引用(SoftReference),弱引用(WeakReference)以及PhantomReference(虚引用),他们被 GC回收的可能性从小到大排列。 强引用(StrongReference) 只要强引用存在,垃圾回收器将...

    iOS中使用对象的弱引用示例代码

    我们都知道使用 UIImage imageNamed 创建的 UIImage 对象会被持有(强引用),如果图片太大会占用内存,损耗 APP 的性能,影响用户体验,如果能改造对其的强引用变为弱引用就可以解决问题。 我们可能会有类似上面的...

    WeakReference(弱引用)让GC需要时回收对象

    我们平常用的都是对象的强引用,如果有强引用存在,GC是不会回收对象的。我们能不能同时保持对对象的引用,而又可以让GC需要的时候回收这个对象呢?.NET中提供了WeakReference来实现。弱引用可以让您保持对对象的...

    强,软,弱,虚1

    强引用可以直接访问目标对象强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出OOM异常,也不会回收强引用所指向的对象强引用可能导致内存泄漏软引用一个对

    解析Android开发优化之:软引用与弱引用的应用

    Java从JDK1.2版本开始,就把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用,本篇文章重点介绍一下软引用和弱引用

    详解Java对象的强、软、弱和虚引用+ReferenceQueue

    主要介绍了详解Java对象的强、软、弱和虚引用+ReferenceQueue的相关资料,需要的朋友可以参考下

    强,软,弱,虚引用非常通俗易懂的代码理解

    前述:除了强引用外,其他引用不是我们所常见的 new出来的对象,而是需要借用3个类SoftReference软引用,WeakReference弱引用,PhantomReference虚引用 1.强引用 概述:即发生OOM(Out Of Memory)内存空间满了也...

    Java的四种引用

    从JDK1.2版本开始,把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

    java四大引用

    java四大引用 四大引用设计作用 强引用 软引用 弱引用 虚引用 java四大引用 java有四种引用类型:强引用、软引用、弱引用、虚引用 四大引用设计作用 ...​ 直到强引用和对象之间的关联被中断,就可以被回收

    【05-面向对象(下)】

    •==和equals比较运算符:==要求两个引用变量指向同一个对象才会返回true。equals方法则允许用户提供自 定义的相等规则。 •Object类提供的equals方法判断两个对象相等的标准与==完全相同。因此开发者通常需要...

    全面解析Java中的引用类型

    在Java中对象以引用来指向JVM的内存区块,这里我们总结了强引用、软引用、弱引用和假象引用(幽灵引用),下面就具体来全面解析Java中的引用类型:

    GCSenderCollection:一个充当 NSDictionary 的类,能够使用(哈希生成)接受对象作为键。 它还可以使用弱引用来避免循环引用

    GCSenderCollection ##1.0.0 充当 NSDictionary 的类,能够使用(哈希生成)接受对象作为键。 它还可以使用弱引用来避免循环引用。... 添加了新的初始化选项(线程安全、容量选择、强引用或弱引用)

    Android避免内存溢出(Out of Memory)方法汇总

    在处理内存引用之前,我们先来复习下什么是强引用、软引用、弱引用、虚引用 强引用:强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。 当内存空间不足,Java虚拟机宁愿抛出...

Global site tag (gtag.js) - Google Analytics