//TO DO
// // main.cpp // learn_smart_point // // Created by New_Life on 2017/8/19. // Copyright © 2017年 chenhuan001. All rights reserved. // #include <iostream> #include <vector> #include <memory>//the head file of smart point class TestBase { public: TestBase() { std::cout << "TestBase construct" << std::endl; } ~TestBase() { std::cout << "TestBase destroy" << std::endl; } void print_info() { std::cout << "TestBase print_info : " << info.c_str() << std::endl; } void set_info(std::string str) { info = str; } std::string info; }; class TestEqual : public TestBase { public: TestEqual() {} ~TestEqual() {} TestEqual& operator = (int a) { std::cout << "in operatr = with int" << std::endl; return *this; } void operator = (bool a) { std::cout << "in operatr = with return void" << std::endl; //return *this; return ; } }; class DebugInfo { public: DebugInfo(const char* info) { _info = info; std::cout << "------in " << _info.c_str() << "------" << std::endl; } ~DebugInfo() { std::cout << "------out " << _info.c_str() << "------" << std::endl; } private: std::string _info; }; void test_equal() { DebugInfo debug_auto_ptr("test_equal"); TestEqual test_equal; test_equal = 1; test_equal = true; TestEqual test_equal1; //test_equal1 = test_equal = false;//whill compile fail test_equal1 = test_equal;//默认赋值函数还是存在的 } void test_auto_ptr() { DebugInfo debug_auto_ptr("test_auto_ptr"); std::auto_ptr<TestBase> base(new TestBase());//封装了下。然后呢 } int main(int argc, const char * argv[]) { //test_equal(); test_auto_ptr(); return 0; }
1. std::auto_ptr源码分析
template <class _Tp> class auto_ptr { private: _Tp* _M_ptr; public: typedef _Tp element_type; //在类内部typedef explicit auto_ptr(_Tp* __p = 0) __STL_NOTHROW : _M_ptr(__p) {} //use default argument and nothrow auto_ptr(auto_ptr& __a) __STL_NOTHROW : _M_ptr(__a.release()) {} //哇 拷贝构造函数里面,直接把之前的release掉了。 auto_ptr& operator=(auto_ptr& __a) __STL_NOTHROW { //赋值函数也是如此。 if (&__a != this) { delete _M_ptr;//直接把原来的delete _M_ptr = __a.release(); } return *this; } ~auto_ptr() __STL_NOTHROW { delete _M_ptr; } _Tp& operator*() const __STL_NOTHROW { return *_M_ptr; } _Tp* operator->() const __STL_NOTHROW {//神奇的用法。 return _M_ptr; } _Tp* get() const __STL_NOTHROW { return _M_ptr; } _Tp* release() __STL_NOTHROW { _Tp* __tmp = _M_ptr; _M_ptr = 0; return __tmp; } void reset(_Tp* __p = 0) __STL_NOTHROW { if (__p != _M_ptr) { delete _M_ptr; _M_ptr = __p; } } #endif /* auto ptr conversions && member templates */ };
上述源码很清晰的说明了auto_ptr的原理。
auto_ptr是在普通的指针上封装了一层,用于管理指针。
构造时传入一个指针,析构是将这个指针delete。
在进行赋值,或者函数参数传递的过程中。会立即把自身保存的指针release掉。
而release是把当前类保存的指针传出去,然后清空。
所以使用auto_ptr会有以下几个问题:
1. 直接调用release后,因为realse本身不会释放保存的指针内存,所以会造成内存泄露。
2. 唯一传递性,传递给其他auto_ptr对象,当前的对象就不在拥有对该指针的控制权。
2. boost::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 ) BOOST_SP_NOEXCEPT : 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 ) BOOST_NOEXCEPT : px( p.release() ) { #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 ); } 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; } // implicit conversion to "bool" #include <boost/smart_ptr/detail/operator_bool.hpp> void swap(scoped_ptr & b) BOOST_NOEXCEPT { T * tmp = b.px; b.px = px; px = tmp; } };
相对于std::auto_ptr
boost::scoped_ptr将拷贝构造函数与赋值重载函数设为私有的,也就禁止了拷贝的情况。也就是不会有std::auto_ptr中的问题2.
因为没有了拷贝的情况,所以boost::scoped_ptr不带有release,所以也不会有std::auto_ptr中的问题1.
但是scoped_ptr的用法就很局限了,只能在作用范围内使用。不允许交换控制权。