这四个东西对使用者来说不难,看懂代码注释里的例子即可,预计1小时左右看懂全部。要去理解其设计思想的话最需要掌握的是模板类的使用,但一般使用者完全不用关心怎么设计的。
使用者的学习路径:
用作对普通指针的转储,防止忘记delete或不知道哪里delete。它跟引用计数没有关系。
头文件的注释就是使用示例
http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/scoped_ptr.h
template <class T, class D = base::DefaultDeleter<T> > class scoped_ptr
其中Deleter可以被替换,默认的Deleter区分是要delete普通指针还是指针数组,或者用free函数删除malloc的内存。
http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/scoped_vector.h
在析构时会delete其元素的vector,知道它的行为即可。
http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/ref_counted.h
为了避免模板类的代码膨胀,引入基类base::subtle::RefCountedBase。基类很简单,就是最基本的引用计数,带AddRef和Release函数。
模 板类template <class T> class RefCounted : public subtle::RefCountedBase相对地就只在Release函数内做特殊处理:delete static_cast<const T*>(this)
另外RefCountedThreadSafeBase和模板类RefCountedThreadSafe是线程安全的版本。
同在ref_counted.h里定义,对RefCounted的子类做引用。scoped_refptr就是构造时调用RefCounted子类的AddRef函数和析构时Release,并提供了操作符的重载。
弱引用指针,用作传递指针但不想更换owner的情况,即明确知道谁去释放但其它引用者不确定其时机,用弱引用指针可随时知道其是否已delete。
http://src.chromium.org/viewvc/chrome/trunk/src/base/memory/weak_ptr.h
看文件里的注释即可。
对函数的闭包封装,头文件的注释就是使用示例
http://src.chromium.org/viewvc/chrome/trunk/src/base/callback.h
要注意注释里提到的对传入参数的要求。Callback最多提供带7个参数的函数封装,其协作类非常多但都不需要去理解。
(理解设计的提示:非常多的模板类,用作抽象各种各样的函数签名;有很多的辅助类和typedef,最好自己整理成图来看清它们的关系)
对Callback的便捷封装,Bind就是返回Callback对象。
http://src.chromium.org/viewvc/chrome/trunk/src/base/bind.h
看看头文件知道它是个模板函数并为不同参数个数做了重载就行了。
(理解设计的提示:查看http://src.chromium.org/viewvc/chrome/trunk/src/base/bind_internal.h文件的注释)
对scoped_ptr的理解:
没有引用计数的类,使用scoped_ptr<class T, class D>。这个模板类中的D是指Deleter,代表如何删除T。引入Deleter最简单的原因就是对数组需要使用delete[]操作符,实际上有4个默认的Deleter。
3个Deleter都是通过重载括号运算符来执行实际的delete操作,而常量长度的数组指针是不允许使用智能指针的,这里也声明出来,能在编译阶段就排除错误。
除了DefaultDeleter,还有一些特殊的Deleter,如disk cache使用的EntryDeleter(disk_cache.h),字节对齐的内存使用的 AlignedFreeDeleter(aligned_memory.h),他们都有自己的括号运算符重载实现,因为这是scoped_ptr模板类要 求的的方式。
scoped_ptr还有个基类template <class T, class D> class scoped_ptr_impl,它实现了scoped_ptr的核心功能,这样抽离出来是因为有些地方不需要更多的功能。这是模板类,多一个函数就可能 多好多个实现。
scoped_ptr_impl定义了内部类Data来继承Deleter,实际就是增加了ptr来保存传入的裸指针(raw pointer / bare pointer)。
struct Data : public D { explicit Data(T* ptr_in) : ptr(ptr_in) {} Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} T* ptr; }; Data data_;
scoped_ptr_impl的主要函数:
explicit scoped_ptr_impl(T* p) : data_(p) { } ~scoped_ptr_impl() { if (data_.ptr != NULL) { // Not using get_deleter() saves one function call in non-optimized // builds. static_cast<D&>(data_)(data_.ptr); } } void reset(T* p) { // This is a self-reset, which is no longer allowed: http://crbug.com/162971 if (p != NULL && p == data_.ptr) abort(); T* old = data_.ptr; data_.ptr = NULL; if (old != NULL) static_cast<D&>(data_)(old); data_.ptr = p; } T* get() const { return data_.ptr; } D& get_deleter() { return data_; } const D& get_deleter() const { return data_; } void swap(scoped_ptr_impl& p2) { using std::swap; swap(static_cast<D&>(data_), static_cast<D&>(p2.data_)); swap(data_.ptr, p2.data_.ptr); } T* release() { T* old_ptr = data_.ptr; data_.ptr = NULL; return old_ptr; }
scoped_ptr是独立的模板类
template <class T, class D = base::DefaultDeleter<T> > class scoped_ptr
和
template <class T, class D> base::scoped_ptr<T[], D>
它有唯一的成员变量
base::internal::scoped_ptr_impl<element_type, deleter_type> impl_
即是组合scoped_ptr_impl,而不是用继承(也就是桥接模式)。impl有的函数,scoped_ptr都有,并多了重载运算符,以便使用者能直接使用智能指针做其它操作:
typedef T element_type
内存释放的流程:scoped_ptr析构=>impl_析构=>调用deleter=>delete element_type
对引用计数的理解:
有引用计数的智能指针则简单多了:
其中T是本身实现了引用计数的类。
为了避免模板类,引入基类:
基类都是这老一套,用变量保存引用数,没啥说的。
模板类:
template <class T> class RefCounted : public subtle::RefCountedBase { public: RefCounted() {} void AddRef() const { subtle::RefCountedBase::AddRef(); } void Release() const { if (subtle::RefCountedBase::Release()) { delete static_cast<const T*>(this); } } protected: ~RefCounted() {} private: DISALLOW_COPY_AND_ASSIGN(RefCounted<T>); };
参考: