1、VC版智能指针

  上次的对其auto_ptr内部结构的实现有些问题:

  (1)、赋值语句

 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 = _Y._Owns; //因为此时万一是下面主函数所写的,就会发生
            }                   //内存空间没人管理,内存泄漏!!!
            _Ptr = _Y.release();
        }
        return *this;
    }

    int main(void){
        int *p = new int(10);
        
        auto_ptr<int> pa(p);
        auto_ptr<int> pa1(pa);
        pa1 = pa;    //上面赋值语句防的就是这种情况,担心同一空间没人管理,导致没法释放!!!
    }

 wKioL1ecBR-RrKVCAAAalJubPKc794.png-wh_50 

  (2)、就是VC版的在release()函数中也可以转移彻底,程序如下:

 _Ty* release()const{
         _Ty *tmp = _Ptr;  //先保留原有空间的地址
        ((auto_ptr<_Ty>*)this)->_Owns = false;
        ((auto_ptr<_Ty>*)this)->_Ptr = 0;  //此时拥有权已经转移的便不再对原有空间的访问。
        return tmp;
}

上面是对自己上次写VC版auto_ptr的赋值语句的修改,上次考虑的情况不周,导致有可能发生内存泄漏!!!

2、标准的VS或Linux下的标准库

  (1)、库里面的函数主要是:reset、release、get、->、 * 、析构、多个赋值 拷贝构造、

  在这个里面对VC进行了改进,没有了所谓的拥有权,其转移的更彻底,消除了安全隐患

  在VS下面不存在拥有权的管理问题,而只是只有一个私有数据,

private:
    _Ty *_ptr;  //就是这一个指针进行管理其空间;

其加上头文件 #include<memory> ,在内部就已经实现好了之间的所有的操作;

#include<iostream>
#include<memory>  //有这个头文件在,智能指针内部都已经实现好了对象之间的拷贝构造,
using namespace std;  //赋值语句,而不会造成内存空间的泄漏!!!

int main(void){
    int *p = new int(10);
    auto_ptr<int> pa(pa);
    
    auto_ptr<int> pa1 = pa; //其实现过程在头文件#include<memory>中均已实现;
}

  (2)、模拟的部分源码如下:

#include<iostream>
using namespace std;

template<class _Ty>
class auto_ptr{
public:
    auto_ptr(_Ty *p = 0) : _ptr(p){}
    auto_ptr(auto_ptr &t) : _ptr(t.release()){} //此时不能加const,因为要对其原有的指向赋值为空
    auto_ptr<_Ty>& operator=(auto_ptr<_Ty> &t){
        if(this != &t){
            reset(t.release());  //先释放自己,在设置其他的对象。
        }
        return *this;
    }
    ~auto_ptr(){
        if(_ptr){
            delete _ptr;
        }
    }
public:
    _Ty& operator*()const{
        return *(get());
    }
    _Ty* operator->()const{
        return get();
    }
    _Ty* get()const{
        return (_ptr);
    }
    _Ty* release(){ //没有拥有权,但是同时也可以达到对对象的控制,
        _Ty *tmp = _ptr; //通过对原先的指针赋空,将其交了出去,自己
        _ptr = 0; //便不再有所控制权了;
        return tmp;//此时释放函数彻底抛弃了拥有权。
    }
    void reset(_Ty *p = 0){
        if(p != _ptr && _ptr){  //这个判断至关重要,看是不是自己设置自己!
            delete _ptr;
        }   //这是重新设置的空间
        _ptr = p;
    }
private:
    _Ty *_ptr; //没有转移权,直接切断联系,断了安全隐患!
};

int main(void){
    int *p = new int(10);
    auto_ptr<int> pa(p);

    cout<<*pa<<endl;
    auto_ptr<int> pa1 = pa;
    auto_ptr<int> pa2;
    pa2 = pa1;
    return 0;
}

/*
int main(void){
    int *p = new int(10);
    auto_ptr<int> pa(p);
    pa.reset(pa);  //自己给自己设置,此时,若没有判断语句,自己把自己将干掉,
    在重新赋值没有任何作用。何来后续的访问呢?
    pa.reset(); //此时释放自己原有空间,并且赋值为空!

    上面get()函数还有其他的用法:
    从智能指针中要回自己的地址,
    int *x = pa.get();
    pa.release(); 此时,-ptr将为空,必须手动释放内存空间;

    delete x;
}
*/

  (3)、没有拥有权如何管理,靠释放函数把指针赋空,为了编写赋值语句,用了一种更好的方案,重新设置的方案。

在源码中还有其他的函数,是为了解决:

pa1 = auto_ptr<int>(new int(100));  //这种问题,临时对象只能是常对象,所以通过其他的方法解决const的问题。

在以后有机会会更深入的剖析,将其他函数一一弄清楚。