先看一个简单的例子:
#include <iostream> using namespace std; #include <boost/scoped_ptr.hpp> using namespace boost; class A { public: A() { cout << "A::A()" << endl; } ~A() { cout << "A::~A()" << endl; } }; /* * */ int main(int argc, char** argv) { scoped_ptr<A> a(new A); return 0; }程序运行后输出结果:
A::A() A::~A()很好,对象被销毁了。
scoped_ptr被设计用来取代std::auto_ptr.
回忆一下auto_ptr的功能,参考我以前的老文章:http://blog.csdn.net/sheismylife/article/details/1694939
auto_ptr也能够像上面例子里自动回收new出来的对象,差别在于auto_ptr有一个所有权转移的特性。这在实现异常安全的代码中是非常有用的。参考herb sutter的exceptional c++系列书籍。
不过在boost::shared_ptr也由于采用了引用计数的实现,比auto_ptr的所有权转移特性更强,而且能够被stl容器接受,不像auto_ptr不能用于stl容器。
所以auto_ptr从宠儿变成了弃儿,最新的C++11标准已经把它废除。
scoped_ptr非常简单,不支持所有权转移。这种实现代码就是利用了前面我的noncopyable文章里面介绍的基本原理。但是实际上并没有从noncopyable继承,不要被文档上的例子代码忽悠。http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/scoped_ptr.htm
真正的实现代码:
template<class T> class scoped_ptr // noncopyable { private: T * px; scoped_ptr(scoped_ptr const &); scoped_ptr & operator=(scoped_ptr const &); typedef scoped_ptr<T> this_type; void operator==( scoped_ptr const& ) const; void operator!=( scoped_ptr const& ) const;私有的copy constructor和copy assignment ,禁止了scoped_ptr之间的拷贝。所有权不能转移了。
同时比较操作符也被禁止了,外面无法调用。
boost里面的实现代码很喜欢用this_type来简化内部的类型引用,值得推荐。
public: typedef T element_type; explicit scoped_ptr( T * p = 0 ): px( p ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px ); #endif } #ifndef BOOST_NO_AUTO_PTR explicit scoped_ptr( std::auto_ptr<T> p ): px( p.release() ) // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_constructor_hook( px ); #endif } #endif ~scoped_ptr() // never throws { #if defined(BOOST_SP_ENABLE_DEBUG_HOOKS) boost::sp_scalar_destructor_hook( px ); #endif boost::checked_delete( px ); }第一个构造函数接受普通指针,保存起来。
第二个构造函数接受auto_ptr,并且通过调用auto_ptr的release函数让auto_ptr不再管理指针的生命周期,然后自己保存该指针。
析构函数利用boost::checked_delete释放px指向的对象。参考我的另一文章:http://blog.csdn.net/sheismylife/article/details/8277908
T & operator*() const // never throws { BOOST_ASSERT( px != 0 ); return *px; } T * operator->() const // never throws { BOOST_ASSERT( px != 0 ); return px; } T * get() const // never throws { return px; }operator* 和 operator-> 使得scoped_ptr就像普通指针一样工组。
// get_pointer(p) is a generic way to say p.get() template<class T> inline T * get_pointer(scoped_ptr<T> const & p) { return p.get(); }全局模板函数可以获得p包含的裸指针。
void swap(scoped_ptr & b) // never throws { T * tmp = b.px; b.px = px; px = tmp; } template<class T> inline void swap(scoped_ptr<T> & a, scoped_ptr<T> & b) // never throws { a.swap(b); } void reset(T * p = 0) // never throws { BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors this_type(p).swap(*this); }成员函数swap可以交换b和this的裸指针。
全局模板函数swap可以交换两个参数内部的裸指针。
reset也利用了这个swap成员函数 将this内部的裸指针交换给了临时对象this_type(p),
因此,如果:
1.调用reset不传递参数,就是清空了自己的裸指针。
或者
2.调用reset传递了另一个指针,就是用这个指针替换了this拥有的裸指针。
不管是哪一种情况,this拥有的原来的裸指针都会被调用delete销毁。因为临时对象this_type(p)通过交换拿到这个指针后,都会在退出swap函数时销毁它。
scoped_ptr也支持if(p) 或者 if(!p)的用法,这里我们再次看到将实现代码放在一个文件中,然后include进来的做法:
// implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp>operator_boo.hpp文件内容如下:
#if ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, < 0x570) ) || defined(__CINT__) operator bool () const { return px != 0; } #elif defined( _MANAGED ) static void unspecified_bool( this_type*** ) { } typedef void (*unspecified_bool_type)( this_type*** ); operator unspecified_bool_type() const // never throws { return px == 0? 0: unspecified_bool; } #elif \ ( defined(__MWERKS__) && BOOST_WORKAROUND(__MWERKS__, < 0x3200) ) || \ ( defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ < 304) ) || \ ( defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x590) ) typedef T * (this_type::*unspecified_bool_type)() const; operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::get; } #else typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::px; } #endif // operator! is redundant, but some compilers need it bool operator! () const // never throws { return px == 0; }其他的编译器不管,GCC版本的实现代码是:
typedef T * this_type::*unspecified_bool_type; operator unspecified_bool_type() const // never throws { return px == 0? 0: &this_type::px; }这里unspecified_bool_type是一个类的成员指针类型,指向了scopec_ptr<T>内部的T的指针。有点拗口:
1.typedef表明这是个类型定义,所以unspecified_bool_type是个类型
2.this_type::*表明这个unspecified_bool_type是个成员指针类型
3.T* 表明这个unspecified_bool_type指针类型指向的是T*类型
整个operator实现就是一个类型转换操作符,如果px为0,则返回0,否则返回内部保存的px裸指针的地址,按照C++规定,只要px裸指针不为空,对它取地址结果是true. 因此下面的代码获得true的返回值:
scoped_ptr<A> a(new A); if (a) { cout << "ok" << endl; }