回忆智能指针

今天去回想了一下智能指针,发现长时间不用,好多知识点都忘记了,所以在这里写一篇博客记录一下。

C++当中没有自动内存回收机制,这样每次new出来的内存都需要我们手动的去delete,这样就会存在忘记的可能性,最终造成内存的泄漏。,所以为了解决这个问题,C++引入了智能指针。

std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::scoped_array、boost::shared_array、boost::weak_ptr、boost:: intrusive_ptr。

其实对于编译器来说,智能指针只不过是一个栈上的对象,通过利用这个对象的构造和析构的特性,实现智能指针的动态的管理,在这个对象的生命周期结束以后,通过析构函数会去释放它所管理的堆上的内存。所有的智能指针都会去重载 “operator->”,这用来直接返回对象的引用,操作对象,访问智能指针直接利用.来操作。

智能指针提供了get( )函数,提供了release( )函数,get函数是得到智能指针的对象,release是释放内存。reset()函数是释放内部管理的内存。

1.auto_ptr


使用auto_ptr的时候切记不能使用auto_ptr,auto_ptr具有转移权限的特性,而且auto_ptr你不能去使用release函数,在这里这个函数只是进行了管理权的释放,并不对对象进行释放,如果想要去释放对象,那么这个时候你就需要去考虑一下reset()函数。

总结:std::auto_ptr 可用来管理单个对象的对内存,但是,请注意如下几点:

(1) 尽量不要使用“operator=”。如果使用了,请不要再使用先前对象。

(2) 记住 release() 函数不会释放对象,仅仅归还所有权。

(3) std::auto_ptr 最好不要当成参数传递(读者可以自行写代码确定为什么不能)。

(4) 由于 std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。

当然,因为权限转移的特性,在这里,auto_ptr还不能去管理一个内存数组。

template <typename T>
class Auto_Ptr
{
public:
    Auto_Ptr(T* ptr=NULL)
        :_ptr(ptr)
    { }
    ~Auto_Ptr()
    {
        delete _ptr;
    }
    Auto_Ptr(Auto_Ptr<T> & a)
    {
        _ptr=a._ptr;
        a._ptr=NULL;
    }

    Auto_Ptr<T> & operator =(Auto_Ptr<T> & a)
    {
        if(a!=this)
        { 
            delete _ptr;
            _ptr=a._ptr;
            a._ptr=NULL;
        }
        return *this;
    }

    T* operator ->()
    {
        return _ptr;
    }

    T& operator *()
    {
        return *_ptr
    }

    T* _ptr;
};

2.scoped_ptr


另外一个引入的内容就是boost库当中的scoped_ptr,scoped_ptr也可以来方便的管理单个的堆内存对象。与auto_ptr不一样的是scoped_ptr是不能拷贝,也不能赋值的,这就叫做独享所有权。

template <typename T>
class Auto_Ptr
{
public:
    Auto_Ptr(T* ptr=NULL)
        :_ptr(ptr)
    {
    }
    ~Auto_Ptr()
    {
        delete _ptr;
    }


    T* operator ->()
    {
        return _ptr;
    }

    T& operator *()
    {
        return *_ptr
    }
protected:
    Auto_Ptr(Auto_Ptr<T> & a);

    Auto_Ptr<T> & operator =(Auto_Ptr<T> & a);
protected:
    T* _ptr;
};

3.shared_ptr


最后需要提一下的就是shared_ptr了,它也是从boost库中所有的,shared_ptr为了更好的解决所有权的问题,内部实现了引用计数的形式。也是用于管理单个堆内存对象。

template<typename T>
class Shared_Ptr
{
public:
    Shared_Ptr(T* ptr)
        :_ptr(ptr)
        ,_count(new int(0))
    {
    }
    ~Shared_Ptr()
    {
        if(--(*_count)==0)
        {
            delete _ptr;
            delete _count;
            _ptr=_count=NULL;
        }
    }
    Shared_Ptr(Shared_Ptr<T> & a)
    {
            _ptr=a._ptr;
            _count=a._count;
            (*_count)++;
    }
    Shared_Ptr<T>& operator =(Shared_Ptr<T>& a)
    {
        if(&a!=this)
        {
            if(--(*_count)==0)
            {
                delete _ptr;
                delete _count;
                _ptr=_count=NULL;
            }
            _ptr=a._ptr;
            _count=a._count;
            (*_count)++;
        }
        return *this;
    }

    //现代一些的写法
    Shared_Ptr<T>& operator =(Shared_Ptr<T> a)
    {
        //在这里把a和this进行交换,然后再析构a的时候,这个时候会让原来_ptr的count--。
        //然后_ptr又指向了a,在这里创建了a的零时变量,这个时候就会给_count++。
        if(a!=&this)
        {
            std::swap(a._ptr,_ptr);
            std::swap(a._count,_count);
        }
        return *this;
    }   
    T* operator ->()
    {
        return _ptr;
    }
    T& operator *()
    {
        return *_ptr;
    }
protected:
    T* _ptr;
    int * _count;
};

另外,管理数组就使用array的指针就好了,使用的方式和上述的三种形式是一样的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值