chrome-智能指针的用法

scoped_ptr

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

// The input parameter must be allocated with new.
 explicit scoped_ptr(C* p = NULL) : ptr_(p) { }
// Reset
void 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引用计数为2
base::WeakPtr<IPC_ThreadEnviroment> pWeakPtr1 = g_IPCAppData->m_spThreadEnviroment->AsWeakPtr();// 执行完后flags引用计数为3
g_IPCAppData->m_spThreadEnviroment = NULL;//// 执行完后flags引用计数为2
base::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_是个无效指针,这时就不要操作它了~

官方:

base::WeakPtr and Cancellation [NOT THREAD SAFE] You can use a base::WeakPtr and base::WeakPtrFactory (in base/memory/weak_ptr.h) to ensure that any invokes can not outlive the object they are being invoked on, without using reference counting. The base::Bind mechanism has special understanding for base::WeakPtr that will disable the task’s execution if the base::WeakPtr has been invalidated. The base::WeakPtrFactory object can be used to generate base::WeakPtr instances that know about the factory object. When the factory is destroyed, all the base::WeakPtr will have their internal “invalidated” flag set, which will make any tasks bound to them to not dispatch. By putting the factory as a member of the object being dispatched to, you can get automatic cancellation.

NOTE: This only works when the task is posted to the same thread. Currently there is not a general solution that works for tasks posted to other threads. See the next section about CancelableTaskTracker for an alternative solution.

注意,NOT THREAD SAFE
必须保证对象 和 该task在同一线程 或者保证task执行时对象不会被删除

参考:
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

猜你喜欢

转载自blog.csdn.net/hgy413/article/details/78872402
今日推荐