智能指针auto_ptr 简介

智能指针是对指针进行一次封装,让指针变得更加智能,更易于管理。
首先了解一下封装指针的几种情况:
     (1)采购拷贝的方式。这样的指针对象既负责创建数据对象,又负责删除数据对象,STL容器对象采用的就是这种方式。采用这种方式的指针对
象责任最清晰。可以参考一下std::vector的C++ Reference文档
public member function

vector::vector

<vector>
explicit vector ( const Allocator& = Allocator() );
explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );
template <class InputIterator>
         vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
vector ( const vector<T,Allocator>& x );
Construct vector
Constructs a vector container object, initializing its contents depending on the constructor version used:

explicit vector ( const Allocator& = Allocator() );
Default constructor: constructs an empty  vector, with no content and a  size of zero.
explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );
Repetitive sequence constructor: Initializes the vector with its content set to a repetition,  n times, of copies of  value.
template <class InputIterator> vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
Iteration constructor: Iterates between  first and  last, setting a copy of each of the sequence of elements as the content of the container.
vector ( const vector<T,Allocator>& x );
Copy constructor: The vector is initialized to have the same contents (copies) and properties as vector  x.
public member function

vector::~vector

~vector ( );
Vector destructor
Destructs the container object. This calls each of the contained element's destructors, and deallocates all the storage capacity allocated by the vector.

(2)采用完全接管的方式,指针对象不负责创建数据对象,但是负责删除数据对象。既不仅接管了源指针指向的对象,还接管了指针指向对象的所有权。auto_ptr<>就是采用这种方式实现的。

(3)采用接管的方式,既不负责创建数据对象,也不负责删除数据对象。STL中的迭代器(iterator)采用的就是这种方式。
(4)完全接管和深层拷贝方式相结合。一般的情况是:拷贝构造和拷贝赋值采用深拷贝方式,而指针构造和指针赋值采用接管方式。这种方式最容易产生运行时内存访问冲突和内存泄露问题,不建议使用。

模拟泛型指针:auto_ptr 采用完全接管的方式。
template  < typename  T >
class  auto_ptr  {
public :
       auto_ptr( T  *p = NULL): m_ptr (p){}
        
       auto_ptr(const auto_ptr< T>& ptr) : m_ptr(ptr.release()){}
        auto_ptr<T>& operator = (const auto_ptr <T>& ptr) {
               if(&ptr != this) {
                      delete m_ptr ;
                      m_ptr = ptr.release();    //释放并移交拥有权,修改了实参对象。
              }
               return *this ;
       }
       ~auto_ptr(){
                delete  m_ptr  ;
       }
         T * release()  const  {
                T * tem =  m_ptr ;
              ((  auto_ptr <  T >*)  this )-> m_ptr  = 0;  
                return  tem;
       }

        Toperator *() {
                return  * m_ptr  ;
       }
         T operator ->() {
                return   m_ptr  ;
       }

private :
         T  *  m_ptr ;

};

struct A {
public:
       A(){}
       A(int num,char ch): m_num(num), m_ch(ch){}

        int m_num ;
        char m_ch ;

};

int main( void) {

        A* a = new A(1,'a');
         auto_ptr  < A  > aPtr(a);

         auto_ptr <  A > bPtr(aPtr);
       std ::cout<<aPtr-> m_ch  <<std :: endl  ; //运行出错因为aPtr已经把指针a的所有权转交给bPtr,把自己的m_ptr设为控指针了。
//delete a   不需要我们去释放a所指向内存空间了。
        return 0;

}

auto_ptr<>采用完全接管的方式,使用auto_ptr<>的好处是:当函数推出时,C++保证会在堆栈清退的过程中自动调用每一个局部对象的析构函数。当调用auto_ptr<>的析构函数时,我们释放了指针所指向的对象空间。
auto_ptr<>不适合作为STL容器的元素类型:
     因为auto_ptr的特点是接管和转移拥有权,因此,auto_ptr对象和它的拷贝不会共享实值对象。然而根据STL容器“值”语义的要求,可拷贝构造意味着一个对象必须和它的拷贝相同。
例如:
std::vector<auto_ptr<A> > v;
v.push_back(aPtr);  
auto_ptr<A> tem = v.front(); //这里改变了容器的元素

所以不要使用容器来装载auto_ptr指针对象。

你可能感兴趣的:(智能指针auto_ptr 简介)