auto_ptr自己实现|临时对象是可度的吗

来源:互联网 发布:游戏矩阵ceo徐乐身价 编辑:程序博客网 时间:2024/05/04 05:40


自己实现auto_ptr,与std::auto_ptr一样。

头文件 _auto_ptr.h

#ifndef __auto_ptr_H_#define __auto_ptr_H_//#define __debug// _auto_ptr.h// 自己实现一个auto_ptr#include <iostream>using namespace std;template <typename T>class _auto_ptr;    template <typename Y>class tmp_class{public:    explicit tmp_class(Y *tp_):tp(tp_){}    Y *tp;};template <typename T>class _auto_ptr{public:    _auto_ptr():p(0)    {        #ifdef __debug        cout<<"_auto_ptr():empty construction of _auto_ptr"<<endl;        #endif    }        template <typename U>    explicit _auto_ptr(U *pu):p( pu )  // 此处若写为 p(pu),则只接受原始指针的兼容赋值(一般是子类指针赋值给基类),                                       // 若写为p((T*)pu),则进行了强制转换,使得float指针可以赋值给int指针                                       // explicit抑制隐式转换    {        if(pu)        {                       #ifdef __debug            cout<<"_auto_ptr(U *pu): construction of _auto_ptr, obj="<<p<<"  "<<endl;            #endif        }else        {            #ifdef __debug            cout<<"_auto_ptr(U *pu): construction of _auto_ptr, null=null"<<endl;            #endif        }    }            _auto_ptr( _auto_ptr<T>& cp):p( 0 )    {        p=cp._release();        #ifdef __debug        cout<<"_auto_ptr(const _auto_ptr<T>& cp):copy construction of _auto_ptr.obj="<<p<<"  "<<endl;        #endif    }            //template<class U>    operator tmp_class<T> ()    {        #ifdef __debug        cout<<"_auto_ptr: hidden convert"<<endl;        #endif        return tmp_class<T>(this->_release());        //return tmp_class<T>(this->p); // 用这句话代替上面一行代码,会发生什么?                                        // 由于auto_ptr的独占性,本对象(A)将指针(控制权)转交给别人(B)以后,A的指针必须                                        // 赋值为NULL,否则当A析构时,会将内存释放,而B还在继续使用该内存单元.                                        // 这一点对  new T 产生的临时对象同样适用,因为该临时对象是可写的。(very important)    }    //    template<class U>   // 如果加上这句,就成为成员函数模板,本函数内的<T>全部换为<U>即可    _auto_ptr( tmp_class<T> cp):p( cp.tp )    {        #ifdef __debug        cout<<"_auto_ptr: tmp_class<T> construction"<<endl;        #endif    }  // tmp_class<T> cp不能为引用        _auto_ptr<T>& operator=(_auto_ptr <T>&cp)    {        if(&cp==this)            return *this;        _clear();        p=cp._release();        #ifdef __debug        cout<<"_auto_ptr::operator=:operator"<<"obj="<<p<<"  "<<endl;        #endif                return *this;    }    ~_auto_ptr()    {        #ifdef __debug         cout<<"~_auto_ptr()"<<endl;        #endif        _clear();    }            T *operator->() {return &(operator*());}    T &operator*() {return *p;}        T* get()    {        return p;    }    private:    void _clear()    {        delete p;        p=0;    }         T *_release()    {       T *tmp=p;       p=0;       return tmp;    }    private:    T  *p;};#endif

main.cpp

#include <iostream>  #include <memory> #define __debug#include "_auto_ptr.h"using namespace std;  class T{public:     T(int v):y(v){cout<<"T 构造"<<endl;}    ~T(){cout<<"T 析构"<<endl;}    int y;    friend ostream &operator<<(ostream &os, const T &t);};ostream &operator<<(ostream &os, const T &t){    cout<<t.y;    return os;    }int main()  {      _auto_ptr<T>p3= _auto_ptr<T>(new T(4) );    cout<<(*p3).y<<endl;    return 0;    }  

结果:

chen@chen-book1:~$ g++ -o cpp c.cpp -gchen@chen-book1:~$ ./cppT 构造_auto_ptr(U *pu): construction of _auto_ptr, obj=0x9605008  _auto_ptr: hidden convert_auto_ptr: tmp_class<T> construction~_auto_ptr()4~_auto_ptr()T 析构chen@chen-book1:~$ 

_auto_ptr需要注意的是:

  不能共享,一个萝卜一个坑!

所以:

【1】因为不能共享,所以拷贝构造/赋值之后,原有的指针就失去了控制权。

【2】拷贝构造和operator=的参数是引用而不是常引用。这带来一个问题,就是临时对象怎么办?就像代码中

 _auto_ptr<T>p3= _auto_ptr<T>(new T(4) );
这使用了另外一个类来中转。它接受临时对象的指针来构造自己,再作为参数对auto_ptr进行构造。这需要一个tmp_class类型参数的构造函数,并将临时对象隐式转换为tmp_class。同时临时对象将自己的指针设置为null,从而交出了控制权。注意new出来的临时对象并非只读,而是可以改变的。


原创粉丝点击