webkit中智能指针

来源:互联网 发布:华为正式推出5g网络 编辑:程序博客网 时间:2024/05/21 10:10
 template<typename T> class PassRefPtr
  • 提供了以下几个构造函数:
    •  PassRefPtr() : m_ptr(0) { }
    • PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
    • template<typename U> PassRefPtr(const RefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
      • 上面这个构造函数将会把RefPtr转换为PassRefPtr。转换的时候会增加内部对象的引用计数
  • 拷贝构造函数
    •     // It somewhat breaks the type system to allow transfer of ownership out of
    •         // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
    •         // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
    •         PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
    • 这里用到了一个leakRef函数也就是将原来的应用PassRefPtr成员m_ptr置空,而将其赋给新的m_ptr。 说白就是吧ptr的控制权交给了新的对象,旧对象已经不能获取到相应的内容指针了
  • 提供的接口,下面指列出了部分重载接口,实际上类似接口都是对m_ptr的操作,也就是对实际指向对象的比较:
    •  T* get() const { return m_ptr; }
    •  T& operator*() const { return *m_ptr; }
    •   T* operator->() const { return m_ptr; }
    •  bool operator!() const { return !m_ptr; }
  • 友元接口
    • template<typename T> inline PassRefPtr<T>  adoptRef(T* p){
    •                                              adoptRef(T* p)   adopted(p);
    •                                       return PassRefPtr<T>(p, true);
    • 传入的T一定是RefCountedBase的子类,在adoptRef函数中就是将  m_adoptionIsRequired修改为false,这个属性的具体作用在“引用计数实现部分介绍”


 template<typename T> class RefPtr 
  • 构造函数:
    • ALWAYS_INLINE RefPtr() : m_ptr(0) { }
    • ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
    •  template<typename U> RefPtr(const PassRefPtr<U>&, EnsurePtrConvertibleArgDecl(U, T));
  • 拷贝构造函数:
    •  ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
    •  template<typename U> RefPtr(const RefPtr<U>& o, EnsurePtrConvertibleArgDecl(U, T)) : m_ptr(o.get()) { refIfNotNull(m_ptr); }
  • 提供接口:
    •  void swap(RefPtr&); 交换两个RefPtr的内部m_Ptr
    •   PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }
            
引用计数的实现,就是ref() and deref(),提供两种方法:
            所有的Node类以及子类的ref()实现(也就是引用计数实现)都来源Node继承于public TreeShared<Node> 。
template<typename NodeType> class TreeShared
这个类使用要求好像比较高,要求是在主线程中使用。其他和RefCountedBase一样存在一个变量m_adoptionIsRequired。这个属性也就是说该对象创建了并且有多处在共享使用它了

另外在WTF中还有一个导出类,也是用于实现引用计数的(ref()),采用的是非模板的形式来实现的。

// This base class holds the non-template methods and attributes.
// The RefCounted class inherits from it reducing the template bloat
// generated by the compiler (technique called template hoisting).
class WTF_EXPORT RefCountedBase 
在这个类的实现中基本原来都是用一个变量来记录一个对象的应用次数,值得注意的是里面还有三个成员变量,总体来讲这三个成员变量用于控制其生命周期的:
  •  bool m_deletionHasBegun:检测是否已经开始析构对象
  •  bool m_adoptionIsRequired
  •  ThreadRestrictionVerifier m_verifier:这个主要是防止在多线程之间共享带来问题
总结:
    PassRefPtr 和 RefPtr 实际都是对指针的分装,提供一些接口。RefPtr更多的是用于作为成员变量和局部变量使用。而PassRefPtr是作为函数返回值使用。按照webkit官方的说法,翻译过来如下:

局部变量和类成员变量:

  • 如果所有权和生命周期能够得到保证可以直接用裸指针(raw pointer).
  • 如果要是需要控制其所有权和生命周期,就可用RefPtr.
  • 局部变量一定不要使用PassRefPtr.

函数参数

  • 如果一个函数不需要这个指针的所有权,可以直接传裸指针,说白了只是用一下,用完了不管里面的内容。
  • 如果需要拥有所有权,也就是会改变他的应用计数,那么就要用PassRefPtr传进来。通常的set函数的参数。 除非特别简单的情况下,否则一般要在函数开始部分将这个参数赋值给一个RefPtr。 一般对这个参数命名可以采用”prp“为前缀

函数返回值:

  • 如果一个函数返回值中对象的所有权不发生转移,那么就直接返回裸指针.常见于getter函数.
  • 如果一个函数返回值是new出来的对象或者所有权发生转移,那么就要用PassRefPtr. 根据上面的原则,一般函数内部产生的变量是RefPtr,所以这个时候需要调用RefPtr的release接口来生成PassRefPtr 

新对象

  • new出来的对象必须立即传给RefPtr
  • 对于RefCounted类型的对象,通过采用adopted函数来进行赋值个RefPtr
  • 最佳的实践方法是将构造函数私有化,然后通过create函数返回一个PassRefPtr赋值给RefPtr
0 0
原创粉丝点击