Boost源码学习二[内存管理一]上
2015-10-22 18:55
176 查看
C++标准库中的auto_ptr,智能指针,部分的解决了获取资源自动释放的问题
在Boost中,提供了6中智能指针:scoped_ptr, scoped_array, shared_ptr, shared_array, weak_ptr, instrusive_ptt,这些智能指针属于smart_ptr组件。
第一个学习scoped_ptr:
特点:内动态管理内存。但所有权不能转让,不能进行赋值操作。(定义的拷贝构造函数和赋值操作符为私有,和noncopyable禁止操作)
看一个Boost程序库开发指南的用法:
第二个学习的scoped_array:
特点:包装了new[]操作符,为动态数组提供了一个代理。但所有权不能转让。释放资源用delete[],没有begin()、end(),迭代器函数,也没有*、->操作符重载。
看一个的用法:
中间插一个unique_ptr:
unique_ptr“唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(通过禁止拷贝语义、只有移动语义来实现)。
unique_ptr指针本身的生命周期:从unique_ptr指针创建时开始,直到离开作用域。离开作用域时,若其指向对象,则将其所指对象销毁(默认使用delete操作符,用户可指定其他操作)。
unique_ptr指针与其所指对象的关系:在智能指针生命周期内,可以改变智能指针所指对象,如创建智能指针时通过构造函数指定、通过reset方法重新指定、通过release方法释放所有权、通过移动语义转移所有权。
接着第三个指针shared_ptr源码:
特点:封装内存创建释放,可自由拷贝和赋值,能安全地放到标准容器中。
使用例子1:
使用例子2:
在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(); }
相关文章推荐
- 第四次作业--个人作业--软件案例分析
- 词法分析实验总结
- 关于对编译原理第二次作业的总结
- Google Analytics与百度统计原理
- 二叉查找树
- 服务器性能之CPU
- 复制文件
- HYSBZ 1036 树的统计Count
- 基于ffmpeg接口sws_scale抽取视频thumbnail 实例
- 如何更新centos的系统时间
- NC中配置Servlet 调用NC服务
- 第四次作业——个人作业——软件案例分析
- HYSBZ 2243 染色
- Vim命令学习笔记
- CSS RESET(让所有的浏览器站在同一条线上)
- 点击startup.bat文件无法启动Tomcat
- 大型开源日志系统比较
- redis unwatch discard
- 用rman恢复备库;遇到备库起不来一个案例 ORA-01152:ORA-01110
- Git学习 -- 标签管理