Juce源码分析(七)弱引用(2)引用对象指针的维护与原对象析构后的通知
来源:互联网 发布:金融投资源码 编辑:程序博客网 时间:2024/04/30 08:02
class MyObject { public: MyObject() { // If you're planning on using your WeakReferences in a multi-threaded situation, you may choose // to create a WeakReference to the object here in the constructor, which will pre-initialise the // embedded object, avoiding an (extremely unlikely) race condition that could occur if multiple // threads overlap while creating the first WeakReference to it. } ~MyObject() { // This will zero all the references - you need to call this in your destructor. masterReference.clear(); } private: // You need to embed a variable of this type, with the name "masterReference" inside your object. If the // variable is not public, you should make your class a friend of WeakReference<MyObject> so that the // WeakReference class can access it. WeakReference<MyObject>::Master masterReference; friend class WeakReference<MyObject>; }; MyObject* n = new MyObject(); WeakReference<MyObject> myObjectRef = n; MyObject* pointer1 = myObjectRef; // returns a valid pointer to 'n' delete n; MyObject* pointer2 = myObjectRef; // returns a null pointer
那么,当delete n时,myObjectRef是如何发生改变的呢?不难猜到,肯定是在MyObject的析构函数里做了处理。每一个类在使用弱引用是都需要添加一个 WeakReference<MyObject>::Master masterReference;的属性(注意,对象的名字都不能改,必须是masterReference),当对象被delete的时候,masterReference通知WeakReference导致引用失效,将指针指针赋值为空指针,其实原理就这么简单,复杂的地方在于弱引用的生命周期的管理,引用对象的创建,复制,传递,析构,不过把这项工作交给上次说到的ReferenceCountedObjectPtr来管理,就没有那么复杂了,ReferenceCountedObjectPtr采用引用计数原理,来控制所指向对象的生命周期,功能相当于shared_ptr。把这两点弄明白,Juce的弱引用遍不再神秘,第一,原对象析构时的通知,因为弱引用是要代替原对象的指针使用,所以引用对象里面维护的是原对象的裸指针,当对象析构时,析构函数将引用对象里的原对象指针赋值为空指针,弱引用的目的便达到了;第二,引用对象生命周期的智能管理,因为引用对象也是使用new关键字在堆中创建的对象,引用对象也存在指针,为了使引用对象智能管理,所以又使用ReferenceCountedObjectPtr来维护引用对象的生命周期,使引用对象也做到智能化管理。整体来说,弱引用相对于原对象来说,是封装了两层,相当于原对象的指针的指针,这两层的实现就是为了达到以上两点的目的。
下面贴出带有关键注释的源码:
/*第二层,SharedPointer对象的智能管理,SharedPointer对象的智能指针*/template <class ObjectType, class ReferenceCountingType = ReferenceCountedObject>class WeakReference{public: /** Creates a null SafePointer. */ inline WeakReference() noexcept {} /** Creates a WeakReference that points at the given object. */ WeakReference (ObjectType* const object) : holder (getRef (object)) {} /** Creates a copy of another WeakReference. */ WeakReference (const WeakReference& other) noexcept : holder (other.holder) {} /** Copies another pointer to this one. */ WeakReference& operator= (const WeakReference& other) { holder = other.holder; return *this; } /** Copies another pointer to this one. */ WeakReference& operator= (ObjectType* const newObject) { holder = getRef (newObject); return *this; } #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS WeakReference (WeakReference&& other) noexcept : holder (static_cast <SharedRef&&> (other.holder)) {} WeakReference& operator= (WeakReference&& other) noexcept { holder = static_cast <SharedRef&&> (other.holder); return *this; } #endif /** Returns the object that this pointer refers to, or null if the object no longer exists. */ ObjectType* get() const noexcept { return holder != nullptr ? holder->get() : nullptr; } /** Returns the object that this pointer refers to, or null if the object no longer exists. */ operator ObjectType*() const noexcept { return get(); } /** Returns the object that this pointer refers to, or null if the object no longer exists. */ ObjectType* operator->() noexcept { return get(); } /** Returns the object that this pointer refers to, or null if the object no longer exists. */ const ObjectType* operator->() const noexcept { return get(); } /** This returns true if this reference has been pointing at an object, but that object has since been deleted. If this reference was only ever pointing at a null pointer, this will return false. Using operator=() to make this refer to a different object will reset this flag to match the status of the reference from which you're copying. */ bool wasObjectDeleted() const noexcept { return holder != nullptr && holder->get() == nullptr; } bool operator== (ObjectType* const object) const noexcept { return get() == object; } bool operator!= (ObjectType* const object) const noexcept { return get() != object; } //============================================================================== /** This class is used internally by the WeakReference class - don't use it directly in your code! @see WeakReference第一层,引用对象,通过Master对象调用clearPointer(),将原对象指针赋值为nullptr */ class SharedPointer : public ReferenceCountingType { public: explicit SharedPointer (ObjectType* const obj) noexcept : owner (obj) {} inline ObjectType* get() const noexcept { return owner; } void clearPointer() noexcept { owner = nullptr; } private: ObjectType* volatile owner; JUCE_DECLARE_NON_COPYABLE (SharedPointer) }; typedef ReferenceCountedObjectPtr<SharedPointer> SharedRef; //============================================================================== /** This class is embedded inside an object to which you want to attach WeakReference pointers. See the WeakReference class notes for an example of how to use this class. @see WeakReference原对象析构时,由原对象中的Master对象成员来通知 */ class Master { public: Master() noexcept {} ~Master() noexcept { // You must remember to call clear() in your source object's destructor! See the notes // for the WeakReference class for an example of how to do this. jassert (sharedPointer == nullptr || sharedPointer->get() == nullptr); } /** The first call to this method will create an internal object that is shared by all weak references to the object. */ SharedPointer* getSharedPointer (ObjectType* const object) { if (sharedPointer == nullptr) { sharedPointer = new SharedPointer (object); } else { // You're trying to create a weak reference to an object that has already been deleted!! jassert (sharedPointer->get() != nullptr); } return sharedPointer; } /** The object that owns this master pointer should call this before it gets destroyed, to zero all the references to this object that may be out there. See the WeakReference class notes for an example of how to do this. */ void clear() noexcept { if (sharedPointer != nullptr) sharedPointer->clearPointer(); } private: SharedRef sharedPointer; JUCE_DECLARE_NON_COPYABLE (Master) };private: SharedRef holder; static inline SharedPointer* getRef (ObjectType* const o) { return (o != nullptr) ? o->masterReference.getSharedPointer (o) : nullptr; }};
配合上一节的内容,通过上面的代码,相信大家可以清晰地看到WeakReference的两层的结构,理解这两层结构实现的方式与目的
- Juce源码分析(七)弱引用(2)引用对象指针的维护与原对象析构后的通知
- Juce源码分析(六)弱引用(1)引用计数对象与引用计数对象指针
- Juce源码分析(八)强引用与弱引用
- Juce源码分析-弱引用(1)
- 对象引用(object reference)与对象指针的区别
- java 按值调用 与 按引用(对象的引用,指针)调用、区分对象与对象引用
- Juce源码分析(一)Juce的优势
- Juce源码分析(五)对象泄露探测器
- java中对象的引用(强引用、软引用、弱引用、虚引用)
- 对象引用与对象指针
- JavaScript对象复制、扩展(改变原对象的引用,避免原对象被动态的改变值);
- 引用传递(传递对象的引用)
- C++异常对象传递的时候,使用普通对象还是指针还是引用(使用引用)
- java--对象引用与对象的区别(转载)
- 对象数组,对象指针,常对象、对象的常引用
- [C++对象模型][2]指针与引用
- [C++对象模型][2]指针与引用
- [C++对象模型][2]指针与引用
- 关于C语言中的强符号、弱符号、强引用和弱引用的一些陋见,欢迎指正
- Java 异步线程FutureTask的使用和SwingWorker
- DedeCMS内容页添加"相关文章"功能
- Class.getSimpleName()的作用
- 黑马程序员—java基础学习--集合类、泛型
- Juce源码分析(七)弱引用(2)引用对象指针的维护与原对象析构后的通知
- document.write()方法详细介绍-含实例
- js function定义函数使用心得
- picker字体
- 在MDI框架结构中防止主框架或子框架标题被自动改变
- Android入门:封装一个HTTP请求的辅助类
- SIFT(尺度不变特征变换匹配)算法详解
- Java 反射 思考
- JAVA 内部静态类--解析静态内部类的使用目的与限制