您的位置:首页 > 其它

Boost源码学习二[内存管理一]上

2015-10-22 18:55 148 查看
C++标准库中的auto_ptr,智能指针,部分的解决了获取资源自动释放的问题
在Boost中,提供了6中智能指针:scoped_ptr, scoped_array, shared_ptr, shared_array, weak_ptr, instrusive_ptt,这些智能指针属于smart_ptr组件。

第一个学习scoped_ptr:

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;

public:

    typedef T element_type;
    explicit scoped_ptr( T * p = 0 ); // never throws
    explicit scoped_ptr( std::auto_ptr<T> p ); // never throws

    ~scoped_ptr() // never throws在其作用域结束时自动删除保存的指针对象,从而正确地回收资源
    void reset(T * p = 0) // never throws删除原来保存的指针,再保存新的指针p,如果p是空指针,那scoped_ptr将不持有任何指针
    {
        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 // never throws返回scoped_ptr内部保存的原始指针
    {
        return px;
    }

    void swap(scoped_ptr & b);// never throws交换两个scoped_ptr保存的原始指针
};

特点:内动态管理内存。但所有权不能转让,不能进行赋值操作。(定义的拷贝构造函数和赋值操作符为私有,和noncopyable禁止操作)
看一个Boost程序库开发指南的用法:
#include <std.hpp>
using namespace std;

#include <boost/smart_ptr.hpp>
#include <boost/smart_ptr/make_unique.hpp>
using namespace boost;

//////////////////////////////////////////

void case1()
{
    scoped_ptr<string> sp(new string("text"));

    assert(sp);
    assert(sp != nullptr);

    cout << *sp << endl;
    cout <<  sp->size() << endl;
}

//////////////////////////////////////////

struct posix_file
{
    posix_file(const char * file_name)
    {   cout << "open file:" << file_name << endl; }
    ~posix_file()
    {   cout << "close file" << endl;   }
};

void case2()
{
    scoped_ptr<posix_file> fp(new posix_file("/tmp/a.txt"));

    scoped_ptr<int> p(new int);

    if (p)
    {
        *p = 100;
        cout << *p << endl;
    }

    p.reset();

    assert(p == 0);
    if (!p)
    {   cout << "scoped_ptr == nullptr" << endl;   }

}

//////////////////////////////////////////

class ptr_owned final
{
    scoped_ptr<int> m_ptr;
};

void bad_case()
{
    scoped_ptr<string> sp(new string("text"));
    //错误的表达如下:   
    //sp++;该指针未定义递增操作符
    //scoped_ptr<string> sp2 = sp;不能拷贝
    //std::prev(sp);未定义递减操作符
    //ptr_owned p;
    //ptr_owned p2(p);不能拷贝
}

//////////////////////////////////////////

void case_unique()
{
    auto p = boost::make_unique<int>(10);

    assert(p && *p == 10);

    p.release();
    assert(!p);

    auto a = boost::make_unique<int[]>(5);
    a[0] = 100;
    a[4] = 500;
    //a[5] = 1000;
}

//////////////////////////////////////////

int main()
{
    case1();
    case2();
    case_unique();
}

第二个学习的scoped_array:

template<class T> class scoped_array : noncopyable {

    public:
      typedef T element_type;

      explicit scoped_array(T * p = 0);//构造函数 
      ~scoped_array(); //析构函数

      void reset(T * p = 0);//重置指针 

      T & operator[](std::ptrdiff_t i) const; //重载operator[]
      T * get() const; 
     
      operator unspecified-bool-type() const; 

      void swap(scoped_array & b); //交换指针
  };

  template<class T> void swap(scoped_array<T> & a, scoped_array<T> & b);


特点:包装了new[]操作符,为动态数组提供了一个代理。但所有权不能转让。释放资源用delete[],没有begin()、end(),迭代器函数,也没有*、->操作符重载。

看一个的用法:

#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <boost/scoped_array.hpp>
using namespace std;
using namespace boost;

#define MAX 10

int main()
{
	scoped_array<char> ptr;
	ptr.reset(new char[MAX]);

	for (int i = 0; i<MAX; i++)
	{
		ptr[i] = 'a' + i;
		cout << ptr[i] << endl;
	}

	system("PAUSE");
	return 0;
}


中间插一个unique_ptr:

unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。

unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。

unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include<memory>
#include<vector>
using namespace std;
class X
{
public:
	//*******************************************************************
	//(1) 动态资源的异常安全保证(利用其RAII特性):
	void foo1()
	{//异常安全的代码。无论是否异常发生,只要px指针成功创建,其析构函数都会被调用,确保动态资源被释放
		unique_ptr<X> px(new X);
		// do something,
	}
	//(2) 返回函数内创建的动态资源 
	unique_ptr<X> foo2()
	{
		unique_ptr<X> px(new X);
		// do something
		return px; //移动语义
	}
	//(3) 可放在容器中(弥补了auto_ptr不能作为容器元素的缺点) 
	void foo3()
	{
		vector<unique_ptr<string>>v;
		unique_ptr<string> p1(new string("abc"));
		v.push_back(std::move(p1));//这里需要显式的移动语义,因为unique_ptr并无copy语义
	}
	//(4) 管理动态数组,因为unique_ptr有unique_ptr<X[]>重载版本,销毁动态对象时调用delete[]
	void foo4()
	{
		unique_ptr<int[]> p(new int[3]{1, 2, 3});
		p[0] = 0;// 重载了operator[]
	}
	//*********************************************************************
};
int main()
{
	//****************基本操作如下:******************************
	//智能指针的创建
	unique_ptr<int> u_i; //创建空智能指针
	u_i.reset(new int(3)); //"绑定”动态对象
	unique_ptr<int> u_i2(new int(4));//创建时指定动态对象
	//所有权的变化
	int *p_i = u_i2.release(); //释放所有权
	unique_ptr<string> u_s(new string("abc"));
	unique_ptr<string> u_s2 = std::move(u_s); //所有权转移(通过移动语义),u_s所有权转移后,变成“空指针”
	u_s2 = nullptr;//显式销毁所指对象,同时智能指针变为空指针。与u_s2.reset()等价
	X x;
	x.foo1();
	x.foo2();
	x.foo3();
	x.foo4();
    return 0;
}

接着第三个指针shared_ptr源码:

template<class T> class shared_ptr
{
private:
	typedef shared_ptr<T> this_type;
public:
	typedef typename boost::detail::sp_element< T >::type element_type;//内部类型定义
	//下面有多种构造函数,为了适应不同情境需要    	
	//默认构造函数,px为指针,pn为计数器(它是一个类shared_count,其默认构造函数设其值为0)
	shared_ptr() BOOST_NOEXCEPT : px(0), pn() // 构造函数,创建一个空指针
	{
	}

#if !defined( BOOST_NO_CXX11_NULLPTR )

	shared_ptr(boost::detail::sp_nullptr_t) BOOST_NOEXCEPT : px(0), pn() // never throws
	{
	}

#endif
	//用Y类型来初始化,Y可能与T是不同类型
	//获得指向类型T的指针p的管理权,同时引用计数置为1。这个构造函数要求Y类型必须能够转换为T类型
	template<class Y> explicit shared_ptr(Y * p) : px(p), pn() 
	{
		boost::detail::sp_pointer_construct(this, p, pn);
	}
	//第一个是shared_ptr将要获得所有权的那个资源,第二个是shared_ptr被销毁时负责释放资源的一个对象,
	//被保存的资源将以d(p)的形式传给那个对象。因此p的值是否有效取决于d。如果引用计数器不能分配成功,
	//shared_ptr抛出一个类型为std::bad_alloc的异常。
	template<class Y, class D> shared_ptr(Y * p, D d) : px(p), pn(p, d)
	{
		boost::detail::sp_deleter_construct(this, p);
	}

#if !defined( BOOST_NO_CXX11_NULLPTR )

	template<class D> shared_ptr(boost::detail::sp_nullptr_t p, D d) : px(p), pn(p, d)
	{
	}

#endif

	// As above, but with allocator. A's copy constructor shall not throw.

	template<class Y, class D, class A> shared_ptr(Y * p, D d, A a) : px(p), pn(p, d, a)
	{
		boost::detail::sp_deleter_construct(this, p);
	}

#if !defined( BOOST_NO_CXX11_NULLPTR )

	template<class D, class A> shared_ptr(boost::detail::sp_nullptr_t p, D d, A a) : px(p), pn(p, d, a)
	{
	}

#endif

	//  generated copy constructor, destructor are fine...

#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

	// ... except in C++0x, move disables the implicit copy

	//从另一个shared_ptr获取管理权,同时引用计数器加1。复制构造函数,两个shared_ptr共同管理一个指针,共享一个指针管理权
	shared_ptr(shared_ptr const & r) BOOST_NOEXCEPT : px(r.px), pn(r.pn)
	{
	}

#endif
	//这使得weak_ptr的使用具有线程安全性,因为指向weak_ptr参数的共享资源的引用计数将会自增(weak_ptr
	//不影响共享资源的引用计数)。如果weak_ptr为空 (r.use_count()==0), shared_ptr 抛出一个类型为bad_weak_ptr的异常。
	template<class Y>explicit shared_ptr(weak_ptr<Y> const & r) : pn(r.pn) // may throw
	{
		boost::detail::sp_assert_convertible< Y, T >();

		// it is now safe to copy r.px, as pn(r.pn) did not throw
		px = r.px;
	}

	template<class Y>
	shared_ptr(weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag)
	BOOST_NOEXCEPT : px(0), pn(r.pn, boost::detail::sp_nothrow_tag())
	{
		if (!pn.empty())
		{
			px = r.px;
		}
	}

	template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )

	shared_ptr(shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty())

#else

	shared_ptr(shared_ptr<Y> const & r)

#endif
	BOOST_NOEXCEPT: px(r.px), pn(r.pn)
	{
		boost::detail::sp_assert_convertible< Y, T >();
	}

	// aliasing,别名构造函数,作用是共享了r的引用计数,但实际持有的却是另外一个可能毫无关系的指针p,而且并不负责p的自动销毁。
	template< class Y >
	shared_ptr(shared_ptr<Y> const & r, element_type * p) BOOST_NOEXCEPT : px(p), pn(r.pn)
	{
	}

#ifndef BOOST_NO_AUTO_PTR
	//这个构造函数从一个auto_ptr获取r中保存的指针的所有权,方法是保存指针的一份拷贝并
	//对auto_ptr调用release。构造后的引用计数为1。而r当然就变为空的。如果引用计数器不能分配成功,则抛出 std::bad_alloc 。
	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);
	}

#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

	template<class Y>
	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);
	}

#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )

	template<class Ap>
	explicit shared_ptr(Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0) : px(r.get()), pn()
	{
		typedef typename Ap::element_type Y;

		boost::detail::sp_assert_convertible< Y, T >();

		Y * tmp = r.get();
		pn = boost::detail::shared_count(r);

		boost::detail::sp_deleter_construct(this, tmp);
	}

#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

#endif // BOOST_NO_AUTO_PTR

#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

	template< class Y, class D >
	shared_ptr(std::unique_ptr< Y, D > && r) : px(r.get()), pn()
	{
		boost::detail::sp_assert_convertible< Y, T >();

		typename std::unique_ptr< Y, D >::pointer tmp = r.get();
		pn = boost::detail::shared_count(r);

		boost::detail::sp_deleter_construct(this, tmp);
	}

#endif

	// assignment
	//重载赋值操作符
	shared_ptr & operator=(shared_ptr const & r) BOOST_NOEXCEPT
	{
		this_type(r).swap(*this);
		return *this;
	}

#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)

	template<class Y>
	shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT
	{
		this_type(r).swap(*this);
		return *this;
	}

#endif

#ifndef BOOST_NO_AUTO_PTR

	template<class Y>
	shared_ptr & operator=(std::auto_ptr<Y> & r)
	{
		this_type(r).swap(*this);
		return *this;
	}

#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

	template<class Y>
	//&&是C++11的新特性,表示右值引用(可以使用临时对象)
	shared_ptr & operator=(std::auto_ptr<Y> && r)
	{
		this_type(static_cast< std::auto_ptr<Y> && >(r)).swap(*this);
		return *this;
	}

#elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )

	template<class Ap>
	typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=(Ap r)
	{
		this_type(r).swap(*this);
		return *this;
	}

#endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

#endif // BOOST_NO_AUTO_PTR

#if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

	template<class Y, class D>
	shared_ptr & operator=(std::unique_ptr<Y, D> && r)
	{
		this_type(static_cast< std::unique_ptr<Y, D> && >(r)).swap(*this);
		return *this;
	}

#endif

	// Move support

#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )

	shared_ptr(shared_ptr && r) BOOST_NOEXCEPT : px(r.px), pn()
	{
		pn.swap(r.pn);
		r.px = 0;
	}

	template<class Y>
#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )

	shared_ptr(shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y, T>::type = boost::detail::sp_empty())

#else

	shared_ptr(shared_ptr<Y> && r)

#endif
	BOOST_NOEXCEPT: px(r.px), pn()
	{
		boost::detail::sp_assert_convertible< Y, T >();

		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;
	}

#endif

#if !defined( BOOST_NO_CXX11_NULLPTR )

	shared_ptr & operator=(boost::detail::sp_nullptr_t) BOOST_NOEXCEPT // never throws
	{
		this_type().swap(*this);
		return *this;
	}

#endif

	void reset() BOOST_NOEXCEPT // never throws in 1.30+
	{
		//this_type()为临时对象,交换后*this成为默认原始状态
		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);
	}

	template<class Y, class D> void reset(Y * p, D d)
	{
		this_type(p, d).swap(*this);
	}

	template<class Y, class D, class A> void reset(Y * p, D d, A a)
	{
		this_type(p, d, a).swap(*this);
	}

	template<class Y> void reset(shared_ptr<Y> const & r, element_type * p)
	{
		this_type(r, p).swap(*this);
	}

	// never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
	//重载解引用操作符,返回指针指向的对象
	typename boost::detail::sp_dereference< T >::type operator* () const
	{
		BOOST_ASSERT(px != 0);
		return *px;
	}

	// never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
	//重载箭头操作符,返回原生态指针
	typename boost::detail::sp_member_access< T >::type operator-> () const
	{
		BOOST_ASSERT(px != 0);
		return px;
	}

	// never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
	//它也可以指向指针,重载了[]操作符
	typename boost::detail::sp_array_access< T >::type operator[] (std::ptrdiff_t i) const
	{
		BOOST_ASSERT(px != 0);
		BOOST_ASSERT(i >= 0 && (i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0));

		return px[i];
	}
	//get可以得到原生态指针
	element_type * get() const BOOST_NOEXCEPT
	{
		return px;
	}

	// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>
	//可以判断是否指针使用者是否唯一
	bool unique() const BOOST_NOEXCEPT
	{
		return pn.unique();
	}
	//返回指针使用者的个数,判断是否唯一是unique比use_count()==1快很多
	long use_count() const BOOST_NOEXCEPT
	{
		return pn.use_count();
	}
	//上面那么多复制构造函数都用到了swap
	/*
	std::swap()源码很简单:
	template <class T> void swap ( T& a, T& b )
	{
	T c(a); a=b; b=c;
	}
	*/
	void swap(shared_ptr & other) BOOST_NOEXCEPT
	{
		std::swap(px, other.px);
		pn.swap(other.pn);
	}

	template<class Y> bool owner_before(shared_ptr<Y> const & rhs) const BOOST_NOEXCEPT
	{
		return pn < rhs.pn;
	}

	template<class Y> bool owner_before(weak_ptr<Y> const & rhs) const BOOST_NOEXCEPT
	{
		return pn < rhs.pn;
	}

	void * _internal_get_deleter(boost::detail::sp_typeinfo const & ti) const BOOST_NOEXCEPT
	{
		return pn.get_deleter(ti);
	}

	void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
	{
		return pn.get_untyped_deleter();
	}

	bool _internal_equiv(shared_ptr const & r) const BOOST_NOEXCEPT
	{
		return px == r.px && pn == r.pn;
	}

	// Tasteless as this may seem, making all members public allows member templates
	// to work in the absence of member template friends. (Matthew Langston)

#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS

private:

	template<class Y> friend class shared_ptr;
	template<class Y> friend class weak_ptr;

#endif
	//shared_ptr仅有的两个数据成员,一个指针,一个引用指针的个数
	element_type * px;                 // contained pointer
	boost::detail::shared_count pn;    // reference counter

};  // shared_ptr
//重载等号和不等号运算符
template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
{
	return a.get() == b.get();
}

template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
{
	return a.get() != b.get();
}

#if __GNUC__ == 2 && __GNUC_MINOR__ <= 96

// Resolve the ambiguity between our op!= and the one in rel_ops

template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
{
	return a.get() != b.get();
}

#endif

#if !defined( BOOST_NO_CXX11_NULLPTR )

template<class T> inline bool operator==(shared_ptr<T> const & p, boost::detail::sp_nullptr_t) BOOST_NOEXCEPT
{
	return p.get() == 0;
}

template<class T> inline bool operator==(boost::detail::sp_nullptr_t, shared_ptr<T> const & p) BOOST_NOEXCEPT
{
	return p.get() == 0;
}

template<class T> inline bool operator!=(shared_ptr<T> const & p, boost::detail::sp_nullptr_t) BOOST_NOEXCEPT
{
	return p.get() != 0;
}

template<class T> inline bool operator!=(boost::detail::sp_nullptr_t, shared_ptr<T> const & p) BOOST_NOEXCEPT
{
	return p.get() != 0;
}

#endif
//重载<比较运算符,可以用于关联容器set和map
template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
{
	return a.owner_before(b);
}

template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
{
	a.swap(b);
}
//指针转换是,不要用C++的static_cast、const_cast,这将造成shared_ptr无法管理
//使用下面的函数来转换,它们还返回shared_ptr<T>类型
template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT
{
	(void) static_cast< T* >(static_cast< U* >(0));

	typedef typename shared_ptr<T>::element_type E;

	E * p = static_cast< E* >(r.get());
	return shared_ptr<T>(r, p);
}

template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT
{
	(void) const_cast< T* >(static_cast< U* >(0));

	typedef typename shared_ptr<T>::element_type E;

	E * p = const_cast< E* >(r.get());
	return shared_ptr<T>(r, p);
}

template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT
{
	(void) dynamic_cast< T* >(static_cast< U* >(0));

	typedef typename shared_ptr<T>::element_type E;

	E * p = dynamic_cast< E* >(r.get());
	return p ? shared_ptr<T>(r, p) : shared_ptr<T>();
}

template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(shared_ptr<U> const & r) BOOST_NOEXCEPT
{
	(void) reinterpret_cast< T* >(static_cast< U* >(0));

	typedef typename shared_ptr<T>::element_type E;

	E * p = reinterpret_cast< E* >(r.get());
	return shared_ptr<T>(r, p);
}

// get_pointer() enables boost::mem_fn to recognize shared_ptr

template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
{
	return p.get();
}

// operator<<

#if !defined(BOOST_NO_IOSTREAM)

#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )

template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
{
	os << p.get();
	return os;
}

#else

// in STLport's no-iostreams mode no iostream symbols can be used
#ifndef _STLP_NO_IOSTREAMS

# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
using std::basic_ostream;
template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
# else
template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
# endif
{
	os << p.get();
	return os;
}

特点:封装内存创建释放,可自由拷贝和赋值,能安全地放到标准容器中。

使用例子1:

#include <exception>

#include <boost/smart_ptr.hpp>
using namespace boost;

//////////////////////////////////////////

void case1()
{
    shared_ptr<int> spi(new int);
    assert(spi);
    *spi = 253;

    shared_ptr<std::string>  sps(new std::string("smart"));
    assert(sps->size() == 5);

    //shared_ptr<int> dont_do_this(new int[10]);
}

//////////////////////////////////////////

void case2()
{
    typedef shared_ptr<std::string> sp_t;
    std::map<sp_t, int> m;

    sp_t sp(new std::string("one"));
    m[sp] = 111;

    shared_ptr<std::exception> sp1(new std::bad_exception());

    auto sp2 = dynamic_pointer_cast<std::bad_exception>(sp1);
    auto sp3 = static_pointer_cast<std::exception>(sp2);
    assert(sp3 == sp1);
}

//////////////////////////////////////////

void case3()
{
    shared_ptr<int> sp(new int(10));
    assert(sp.unique());

    shared_ptr<int> sp2 = sp;

    assert(sp == sp2 &&
     sp.use_count() == 2);

    *sp2 = 100;
    assert(*sp == 100);

    sp.reset();
    assert(!sp);
}

//////////////////////////////////////////

class shared
{
private:
    shared_ptr<int> p;
public:
    shared(shared_ptr<int> p_):p(p_){}
    void print()
    {
        std::cout << "count:" << p.use_count()
            << " v=" <<*p << std::endl;
    }
};

void print_func(shared_ptr<int> p)
{
    std::cout << "count:" << p.use_count()
        << " v=" <<*p << std::endl;
}

void case4()
{
    shared_ptr<int> p(new int(100));
    shared s1(p), s2(p);

    s1.print();
    s2.print();

    *p = 20;
    print_func(p);

    s1.print();
}

//////////////////////////////////////////

void case5()
{
    auto sp = make_shared<std::string>("make_shared");
    auto spv = make_shared<std::vector<int> >(10, 2);
    assert(spv->size() == 10);
}

//////////////////////////////////////////

void case6()
{
    typedef std::vector<shared_ptr<int> > vs;
    vs v(10);

    int i = 0;
    for (auto pos = v.begin(); pos != v.end(); ++pos)
    {
        (*pos) = make_shared<int>(++i);
        std::cout << *(*pos) << ", ";
    }
    std::cout << std::endl;

    for (auto& ptr : v)
    {
        ptr = make_shared<int>(++i);
        std::cout << *ptr << ", ";
    }
    std::cout << std::endl;

    shared_ptr<int> p = v[9];
    *p = 100;
    std::cout << *v[9] << std::endl;
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
}

使用例子2:

#include <boost/core/ignore_unused.hpp>
#include <boost/smart_ptr.hpp>
using namespace boost;

//////////////////////////////////////////

class sample
{
private:
    class impl;
    shared_ptr<impl> p;
public:
    sample();
    void print();
};

class sample::impl
{
public:
    void print()
    {   std::cout << "impl print" << std::endl;}
};

sample::sample():p(new impl){}

void sample::print()
{   p->print();}

void case1()
{
    sample s;
    s.print();
}

//////////////////////////////////////////

class abstract
{
public:
    virtual void f() = 0;
    virtual void g() = 0;
protected:
    virtual ~abstract() = default;
};

class impl:public abstract
{
public:
    impl() = default;
    virtual ~impl() = default;
public:
    virtual void f() 
    {   std::cout << "class impl f" << std::endl; }
    virtual void g() 
    {   std::cout << "class impl g" << std::endl; }
};

shared_ptr<abstract> create()
//{   return shared_ptr<abstract>(new impl);}
{   return make_shared<impl>();}

void case2()
{
    auto p = create();
    p->f();
    p->g();

    abstract *q = p.get();
    boost::ignore_unused(q);
    //delete q;
}

//////////////////////////////////////////

class socket_t {};

socket_t* open_socket()
{
    std::cout << "open_socket" << std::endl;
    return new socket_t;
}

void close_socket(socket_t * s)
{
    std::cout << "close_socket" << std::endl;
}

void case3()
{
    socket_t *s = open_socket();
    shared_ptr<socket_t> p(s, close_socket);
    //shared_ptr<socket_t> p(s, &close_socket);
}

//////////////////////////////////////////

bool case4()
{
    auto p = make_shared<int>(776);

    assert(p);
    if(p)
    {
        std::cout << "explicit cast" << std::endl;
    }

    //return !!p;
    return static_cast<bool>(p);
}

//////////////////////////////////////////

void any_func(void* p)
{   std::cout << "some operate" << std::endl;}

void case5()
{
    shared_ptr<void> p(nullptr,any_func);
}

//////////////////////////////////////////

void case6()
{
    auto p1 = make_shared<std::pair<int, int>>(0,1);

    shared_ptr<int> p2(p1, &p1->second);

    assert(p1.use_count() == 2 &&
           p1.use_count() == p2.use_count());
    assert((void*)p1.get() != (void*)p2.get());
    assert(&p1->second== p2.get());
}

//////////////////////////////////////////
#include <boost/smart_ptr/owner_less.hpp>

void case7()
{
    typedef shared_ptr<int> int_ptr;
    typedef owner_less<int_ptr> int_ptr_less;

    int_ptr p1(new int(10));
    int n = 20;
    int_ptr p2(p1, &n);

    assert(!int_ptr_less()(p1, p2) &&
           !int_ptr_less()(p2, p1));

    typedef std::set<int_ptr> int_set;

    int_set s;
    s.insert(p1);
    s.insert(p2);
    assert(s.size() == 1);
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
    case6();
}



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: