• 智能指针(auto_ptr)vc版


    auto_ptr包含于头文件 #include<memory> 其中<vector><string>这些库中也存有。auto_ptr 能够方便的管理单个堆内存对象,在你不用的时候自动帮你释放内存。

    auto_ptr的设计目的:

            局部对象获取的资源(内存),当函数退出时,它们的析构函数被调用,从而自动释放这些资源,但是,如果以显式手法获得的资源(称为动态分配内存空间如:new、malloc等)没有绑定在任何对象身上,必须以显式手法释放。(如:delete,free等)。
             因此,这会出现一些麻烦,如我们忘掉delete,或者return语句在delete之前,例如:
     1 #include<iostream>
     2 using namespace std;
     3 int main()
     4 {
     5     int *p=new int(10);
     6     if(*p>2)
     7         return 0;
     8     delete p;
     9     p=NULL;
    10 }
    在没有delete之前函数已经返回。同时,如果此函数有异常出现时,函数将立刻退离,根本不会调用函数尾端的delete语句,这就会使内存遗失。当然我们也可以防止这种情况发生那就是在函数中用try。。catch语句,但是这回显的程序很复杂和累赘。
            如果使用智能指针,无论在任何情况下,只要自身摧毁就一定会释放资源。因为智能指针原理就是将指针转换为类对象,由于对象被销毁会自动调用类中的析构函数,释放对象所指向的内存空间从而达到自动释放资源的目的。
    注意:auto_ptr它是“它所指向的对象”的拥有者。所以。当身为对象拥有者的auto_ptr被摧毁,auto_ptr要求一个对象只有一个拥有者,严禁一物二主(之后的拥有权转移也会提到)
    一个版本的auto_ptr是Linux和VS中使用的,另一个是VC版本的,下面是VC版本的auto_ptr的源代码剖析:
    c中的auto_ptr:
            源码:
    vc:
    
    template<class _Ty>
        class auto_ptr {
    public:
        typedef _Ty element_type;
        explicit auto_ptr(_Ty *_P = 0) _THROW0()
            : _Owns(_P != 0), _Ptr(_P) {}
        auto_ptr(const auto_ptr<_Ty>& _Y) _THROW0()
            : _Owns(_Y._Owns), _Ptr(_Y.release()) {}
        auto_ptr<_Ty>& operator=(const auto_ptr<_Ty>& _Y) _THROW0()
            {if (this != &_Y)
                {if (_Ptr != _Y.get())
                    {if (_Owns)
                        delete _Ptr;
                    _Owns = _Y._Owns; }
                else if (_Y._Owns)
                    _Owns = true;
                _Ptr = _Y.release(); }
            return (*this); }
        ~auto_ptr()
            {if (_Owns)
                delete _Ptr; }
        _Ty& operator*() const _THROW0()
            {return (*get()); }
        _Ty *operator->() const _THROW0()
            {return (get()); }
        _Ty *get() const _THROW0()
            {return (_Ptr); }
        _Ty *release() const _THROW0()
            {((auto_ptr<_Ty> *)this)->_Owns = false;
            return (_Ptr); }
    private:
        bool _Owns;
        _Ty *_Ptr;
        };

     解析代码:

    1.
    #include <iostream>
    #include <vld.h>
    int main()
    {
        int *p=new int(10)//初始化指针
            return 0;
    }

    运行结果:

     由于没有用delete释放内存空间,所以造成内存空间浪费了四个字节。

    2.

    #include<iostream>
    using namespace std;
    
    class Test
    {
    public:
        void fun()
        {
            cout << "Test::fun()" << endl;
        }
    };
    template<class _Ty>
    class auto_ptr
    {
    public:
        explicit auto_ptr(_Ty *_P = 0) :_Owns(_P != 0), _Ptr(_P)
        {}
        auto_ptr(const auto_ptr<_Ty>&_Y):_Owns(_Y._Owns),_Ptr(_Y.release()){}
        auto_ptr<_Ty>&operator=(const auto_ptr<_Ty>&_Y)//赋值运算符重载
        {
            if(this!=&_Y)//判断自身赋值给自身
            {
                if (_Ptr != _Y._Ptr)//判断两指针是否指向同一内存
                {
                    if (_Owns)    //判断该对象是否有拥有权
                        delete _Ptr;  //释放成员指针指向的内存空间
                    _Owns = _Y._Owns;   //修改该指针的拥有权
                }
                else if (_Y._Owns)
                    _Owns = true;
                _Ptr = _Y.release();  //修改_Y的拥有权,并将_Y的_Ptr赋值给该成员_Ptr从而使该对象具有_Y._Ptr指向空间的拥有权
            }
            return (*this);
        }
        _Ty& operator*()
        {
            return *_Ptr;
        }
        _Ty* operator->()
        {
            return _Ptr;
        }
        _Ty*release()const
        {
            ((auto_ptr<_Ty>*)this)->_Owns = false;
            return (_Ptr);
        }
        ~auto_ptr()
        {
            if (_Owns)
                delete _Ptr;
        }
    private:
        bool _Owns;//拥有权
        _Ty *_Ptr;
    
    };
    
    int main()
    {
        int *p = new int(10);
        auto_ptr<int> pl(p);
        cout << *pl << endl;
        Test *pc = new Test;
        auto_ptr<Test> temp(pc);
        temp->fun();
        auto_ptr<int>pal = pl;
        cout << *pal << endl;
        auto_ptr<int>pt;
        pt = pal;
        cout << *pal << endl;
        cout << *pt << endl;
        
        return 0;
    }
       auto_ptr(const auto_ptr<_Ty>&_Y):_Owns(_Y._Owns),_Ptr(_Y.release()){}//此处的const并非意味你不能更改auto_ptr所拥有的对象,而是意味你不能更改auto_ptr的拥有权。(通俗讲就是如果使用const auto_ptr作为参数,对新对象的任何赋值操作都将导致编译期错误。就常数特性而言,const auto_ptr比较类似常数指针(T*const p),而非指向常数的指针(const  T*p)——尽管其语法看上去比较像后者。所以_Y.release()改变了_Y.Owns的值不影响函数运行。
    1 _Ty*release()const
    2  {
    3   ((auto_ptr<_Ty>*)this)->_Owns = false;
    4   return (_Ptr);
    5  }

             同时这里因为函数是const修饰的常函数所以不能对其进行修改,但是((auto_ptr<_Ty>*)this)其意义是将const (auto_ptr<_Ty>*)类型强制转换为(atuo_ptr<_Ty*>类型,这样就可以对_Owns进行修改,但是这只能在强制之时进行修改,一旦执行完强转其类型依然变为原来的const (auto_ptr<_Ty>*)类型,使其它方法无法修改其中数据。

    运行结果  :
    no memory leaks 无内存泄漏
         这里有一些问题,为什么*pal的拥有权已经转移却还能输出呢?因为vc版的auot_ptr就是将拥有权转移后,除了不能够对其多次析构外,还可以对其进行操作,这就不好了,你都已经分手了,还不放手。在VS版本上对拥有权有更好的管理。
  • 相关阅读:
    偶的机机升级了
    质疑 Sina.com 的金牌榜[图文]
    一道JAVA作业题
    北京出差总结
    我拿什么奉献给你
    CSDN无限极树PHP+MySQL版
    极大强连通分量的Tarjan算法
    NOI2001 炮兵阵地详解
    单调队列及其应用
    some english website
  • 原文地址:https://www.cnblogs.com/ycw1024/p/10420777.html
Copyright © 2020-2023  润新知