boost智能指针
1、RAII机制
RAII-- 资源获取即初始化,Resource Acquisition Is Initialization。是指使用资源的类在构造函数中申请资源,然后使用,在析构函数中释放资源。即以对象的方式管理指针。
★对象在栈上创建资源,由于作用域限制,过了作用域自动释放资源;
★对象在堆上创建资源,如new的方式,需要手动delete,可能造成内存泄漏。
2、boost的解决方式--智能指针
boost.smart_ptr库位于<boost/smart_ptr.hpp>提供六种智能指针:scoped_ptr/scoped_array/shared_ptr/shared_ptr/weak_ptr/initrusive_ptr.特点是轻量级对象、异常安全、要求指向的类型T的析构函数不能抛出异常。本文只介绍scoped_ptr、shared_ptr和weak_ptr。
3、scoped_ptr
3.1、特点
包装了new操作符在堆上分配的动态对象,保证及时自动释放;原始指针的权限不能转让,即该智能指针只能在该作用域中使用,不希望被转让。
3.2、类实现
template<classT> 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;//禁止不等操作
public:
typedef T element_type;
explicitscoped_ptr( T * p = 0 ): px( p ) // never throws 显式构造
{
#ifdefined(BOOST_SP_ENABLE_DEBUG_HOOKS)
boost::sp_scalar_constructor_hook( px);
#endif
}
~scoped_ptr()// never throws 析构
{
boost::checked_delete( px );
}
void reset(T * p = 0) // never throws 重置指针
{
BOOST_ASSERT( p == 0 || p != px ); //catch self-reset errors
this_type(p).swap(*this);
}
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 BOOST_NOEXCEPT //获取原始指针
{
return px;
}
void swap(scoped_ptr & b)BOOST_NOEXCEPT //交换指针
{
T * tmp = b.px;
b.px = px;
px = tmp;
}
};
3.3、说明
★ 接受的指针必须是new在堆上分配的
★ scoped_ptr接受一个new出来的指针,并在析构函数中自动释放
★reset函数更改保护的原始指针,尽量不用,以防原始指针失控
★ scoped_ptr不支持拷贝构造、赋值、等于、不等于操作,因此基于这些操作符的stl算法不能使用。
3.4、使用
只需要将使用原始指针的地方替换为scoped_ptr即可:
std::stringpStr = new std::string("hello");
scoped_ptr<string> sp(pStr);
std::stringsStr = *sp;
size_tnSize = sp->size();
注意scoped_ptr是不能进行赋值的。
4、shared_ptr
4.1、特点
包装new出来的原始指针;实现对原始指针的引用计数,只有在引用计数为0时才会被释放,因此可以支持拷贝和赋值;可以放在stl容器中。
4.2、类实现
template<classT> class shared_ptr
{
public:
typedef typenameboost::detail::sp_element< T >::type element_type;
shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn()// never throws in 1.30+
{
}
template<class Y>
explicit shared_ptr( Y * p): px( p ), pn() // Y must be complete
{
boost::detail::sp_pointer_construct(this, p, pn );
}
// Requirements: D's copy constructor mustnot throw 执行删除器D
// shared_ptr will release p by callingd(p)
template<class Y, class D>shared_ptr( Y * p, D d ): px( p ), pn( p, d )
{
boost::detail::sp_deleter_construct(this, p );
}
shared_ptr( shared_ptr const & r )BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
template<class Y>
explicit shared_ptr( std::auto_ptr<Y>& r ): px(r.get()), pn()
{
boost::detail::sp_assert_convertible< Y, T >();
Y * tmp = r.get();
pn = boost::detail::shared_count( r );
boost::detail::sp_deleter_construct(this, tmp );
}
template<class Y>
shared_ptr & operator=(std::auto_ptr<Y> & r )
{
this_type( r ).swap( *this );
return *this;
}
shared_ptr( shared_ptr && r )BOOST_NOEXCEPT : px( r.px ), pn()
{
pn.swap( r.pn );
r.px = 0;
}
shared_ptr & operator=( shared_ptr&& r ) BOOST_NOEXCEPT
{
this_type( static_cast< shared_ptr&& >( r ) ).swap( *this );
return *this;
}
template<class Y>
shared_ptr & operator=(shared_ptr<Y> && r ) BOOST_NOEXCEPT
{
this_type( static_cast<shared_ptr<Y> && >( r ) ).swap( *this );
return *this;
}
void reset() BOOST_NOEXCEPT // never throwsin 1.30+
{
this_type().swap(*this);
}
template<class Y> void reset( Y * p )// Y must be complete
{
BOOST_ASSERT( p == 0 || p != px ); //catch self-reset errors
this_type( p ).swap( *this );
}
element_type * get() const BOOST_NOEXCEPT
{
return px;
}
private:
element_type * px; // contained pointer
boost::detail::shared_count pn; // reference counter
}; // shared_ptr
4.3、说明
shared_ptr支持拷贝和赋值,只不过引用计数+1;支持比较操作,相当于原始指针的比较。
4.4、用法
shared_ptr<int>sp(new int(10));
shared_ptr<int>sp2 = sp;
assert(sp== sp2 && sp.use_count() == 2 );
*sp2 =100;
assert(*sp== 100);
sp.reset();//停止sp的引用
assert(!sp);
5、weak_ptr
5.1特点
weak_ptr没有重载*和->,因此其并不能当作普通指针使用;其行为是对shared_ptr的一种协助,帮助监控当前引用计数,在需要的时候获取shared_ptr对象。
5.2、类实现
template<classT> class weak_ptr
{
public:
typedef typenameboost::detail::sp_element< T >::type element_type;
weak_ptr() BOOST_NOEXCEPT : px(0), pn() //never throws in 1.30+
{
}
weak_ptr( weak_ptr const & r )BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
{
}
weak_ptr & operator=( weak_ptr const& r ) BOOST_NOEXCEPT
{
px = r.px;
pn = r.pn;
return *this;
}
template<class Y>
weak_ptr & operator=(shared_ptr<Y> const & r ) BOOST_NOEXCEPT
{
boost::detail::sp_assert_convertible< Y, T >();
px = r.px;
pn = r.pn;
return *this;
}
shared_ptr<T> lock() const BOOST_NOEXCEPT
{
return shared_ptr<T>( *this,boost::detail::sp_nothrow_tag() );
}
long use_count() const BOOST_NOEXCEPT
{
return pn.use_count();
}
bool expired()const BOOST_NOEXCEPT
{
return pn.use_count() == 0;
}
void reset() BOOST_NOEXCEPT // never throwsin 1.30+
{
this_type().swap(*this);
}
void swap(this_type & other)BOOST_NOEXCEPT
{
std::swap(px, other.px);
pn.swap(other.pn);
}
private:
element_type * px; // contained pointer
boost::detail::weak_count pn; // referencecounter
}; // weak_ptr
5.3、说明
★lock函数从被观测的sharped_ptr获得一个可用sharped_ptr对象;
★expired函数判断weak_ptr观察的对象是否失效
★use_count函数获取被观察对象的指针引用计数
5.4、用法
shared_ptr<int>sp(new int(10));
assert(sp.use_count()== 1);
weak_ptr<int>wp(sp);
assert(wp.use_count()== 1);
if ( !wp.expired())
{
shared_ptr<int> sp2 = wp.lock();
*sp2 = 100;
assert(wp.use_count() == 2);
}