今天去回想了一下智能指针,发现长时间不用,好多知识点都忘记了,所以在这里写一篇博客记录一下。
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的指针就好了,使用的方式和上述的三种形式是一样的。