chrome-智能指针的用法

来源:互联网 发布:建筑软件上市公司 编辑:程序博客网 时间:2024/06/11 06:20

scoped_ptr

代码来自:base\memory\scoped_ptr.h
它包装了new操作符,保证在析构时会删除这个对象:
构造一般用法:

// The input parameter must be allocated with new. explicit scoped_ptr(C* p = NULL) : ptr_(p) { }// Resetvoid reset(C* p = NULL) {    if (p != ptr_) {      enum { type_must_be_complete = sizeof(C) };      delete ptr_;      ptr_ = p;    }  }

即初始化时new或reset时new,在析构或reset时自动释放

 // Destructor.  If there is a C object, delete it.  // We don't need to test ptr_ == NULL because C++ does that for us.  ~scoped_ptr() {    enum { type_must_be_complete = sizeof(C) };    delete ptr_;  }

注意:它不能用于继承于RefCounted或RefCountedThreadSafe的类,因为它自己实现了Add和Release

scoped_refptr

代码来自:base\memory\ref_counted.h
字面多了个ref,即相对于scoped_ptr多了引用计数功能, 用于继承于RefCounted或RefCountedThreadSafe的类,所以它自身不需要像scoped_ptr那样实现Add和Release


  • 一般来说scoped_refptr所包含的对象初始引用计数为0(new RefCounted对象时初始ref_count_为0),
    将其放入scoped_refptr时会导致引用计数+1
    引用计数为0时删除scoped_refptr所包含的对象

Chromium 中Scoped_refptr使用场景一般为明确为某一线程所拥有的对象、或者某一类聚合的另一个类。对于跨线程使用的对象场合,一般使用弱指针。
注意清除不要用.Release,直接=NULL就好了,

Weakptr

弱引用指针,是为了 解决引用环问题,在chrome中继承于base::SupportsWeakPtr来使用弱引用指针

template <class T>class SupportsWeakPtr { public:  SupportsWeakPtr() {}  WeakPtr<T> AsWeakPtr() {    return WeakPtr<T>(weak_reference_owner_.GetRef(), static_cast<T*>(this));  }  // Indicates that this object will be used on another thread from now on.  void DetachFromThread() {    weak_reference_owner_.DetachFromThread();  } private:  internal::WeakReferenceOwner weak_reference_owner_;  DISALLOW_COPY_AND_ASSIGN(SupportsWeakPtr);};
WeakReference WeakReferenceOwner::GetRef() const {  if (!HasRefs())// 引用计数    flag_ = new WeakReference::Flag();  return WeakReference(flag_);}

1.AsWeakPtr函数是每次都返回一个WeakPtr对象,多次就返回多个WeakPtr对象
2.所有的WeakPtr对象都指向同一个internal::WeakReferenceOwner::GetRef()
3.internal::WeakReferenceOwner::GetRef()总是指向唯一的flags
4.flags是有引用计数的,所以它能保证弱引用比它引用的ptr对象生命周期要长,即Object销毁时它仍然存在,直到所有的WeakReference ref_都销毁时

我们再回头看下代码:
1.Obj的AsWeakPtr初始生成了一个 WeakPtr,此时flags的引用计数初始化为2(1为Obj的SupportsWeakPtr基类,另1为WeakPtr)
2.WeakPtr赋值给另一个WeakPtr,flags引用计数+1
3.Obj的AsWeakPtr再次生成了一个 WeakPtr,此时flags引用计数+1

即所有WeakPtr和Obj都拥有同一个flags,flags的引用计数为它们的总数
任一 WeakPtr析构或者Obj析构,flags的引用计数-1
flags的引用计数为0时,flags会析构
示例代码如下:

base::WeakPtr<IPC_ThreadEnviroment> pWeakPtr = g_IPCAppData->m_spThreadEnviroment->AsWeakPtr();// 执行完后flags引用计数为2base::WeakPtr<IPC_ThreadEnviroment> pWeakPtr1 = g_IPCAppData->m_spThreadEnviroment->AsWeakPtr();// 执行完后flags引用计数为3g_IPCAppData->m_spThreadEnviroment = NULL;//// 执行完后flags引用计数为2base::WeakPtr<IPC_ThreadEnviroment> pWeakPtr2 = pWeakPtr;// 执行完后flags引用计数为3

最后一个疑问:当obj析构时,WeakPtr怎么知道它无效了?
同样在于flags,flags有个is_valid_成员变量,当obj析构时,因为obj是继承于SupportsWeakPtr,而SupportsWeakPtr析构时肯定会把成员变量Internal::WeakReferenceOwner也释放,Internal::WeakReferenceOwner拥有flags,所以它把is_valid_置为flase,而WeakPtr就靠is_valid_判断它拥有的obj的指针是否有效:

  T* get() const { return ref_.is_valid() ? ptr_ : NULL; }

如果get返回NULL,表示ptr_是个无效指针,这时就不要操作它了~

参考:
http://blog.csdn.net/zero_lee/article/details/7907192
http://blog.csdn.net/hursing/article/details/38777181
https://www.cnblogs.com/sybtjp/archive/2012/04/27/2473161.html
https://www.zhihu.com/question/26851369

原创粉丝点击