c/c 常为人诟病的一点是没有像java一样的内存回收机制(gc),因而对内存的管理和访问十分容易出错。c语言作为一种相对低级和轻量级的语言,内存的使用大部分都需要程序员自己操作,如创建数组和链表等,内存访问越界、悬浮指针和野指针等问题屡见不鲜。不过根据个人感觉,相对来说,c语言更底层,没有c 的抽象能力强,只要细心,这些问题阻止不了c的流行,而c 就复杂多了,完全靠程序员来做这些事很容易犯错,因此c 提供了各种各样的容器如vector、map和智能指针,大大减轻了程序员们对内存管理和使用的负担。
智能指针其实就是类对象,程序员将指针交给这些对象,指针被封装起来,内存的管理交由这些对象负责,我们通过其提供的接口使用指针。
template
class auto_ptr
{
private:
t*ap;
public:
//constructor & destructor-----------------------------------(1)
explicit auto_ptr(t*ptr=0)throw():ap(ptr)
{
}
~auto_ptr()throw()
{
delete ap;
}
//copy & assignment--------------------------------------------(2)
auto_ptr(auto_ptr& rhs)throw():ap(rhs.release())
{
}
template
auto_ptr(auto_ptr&rhs)throw():ap(rhs.release())
{
}
auto_ptr& operator=(auto_ptr&rhs)throw()
{
reset(rhs.release());
return*this;
}
template
auto_ptr& operator=(auto_ptr&rhs)throw()
{
reset(rhs.release());
return*this;
}
//dereference----------------------------------------------------(3)
t& operator*()const throw()
{
return*ap;
}
t* operator->()const throw()
{
returnap;
}
//helper functions------------------------------------------------(4)
//value access
t* get()const throw()
{
returnap;
}
//release owner ship
t* release()throw()
{
t*tmp(ap);
ap=0;
return tmp;
}
//reset value
void reset(t*ptr=0)throw()
{
if(ap!=ptr)
{
deleteap;
ap=ptr;
}
}
//special conversions-----------------------------------------------(5)
template
struct auto_ptr_ref
{
y*yp;
auto_ptr_ref(y*rhs):yp(rhs){}
};
auto_ptr(auto_ptr_refrhs)throw():ap(rhs.yp)
{
}
auto_ptr& operator=(auto_ptr_refrhs)throw()
{
reset(rhs.yp);
return*this;
}
template
operator auto_ptr_ref()throw()
{
returnauto_ptr_ref(release());
}
template
operator auto_ptr()throw()
{
returnauto_ptr(release());
}
};
这是auto_ptr的类源码,可以看到其提供的接口。智能指针的构造函数一般声明成explicit,即不允许隐式转换,需要显式调用构造函数生成智能指针对象。既然是指针,就必须可以实现指针的功能,并且用起来要尽量像指针,因此智能指针都重载了operator *()和operator ->(),但是不支持指针的数学运算。
智能指针的种类不少,有auto_ptr、scoped_ptr、unique_ptr、shared_ptr、weak_ptr、shared_array等。auto_ptr是c 98中的,比较粗糙,使用比较简单,也不安全,因为不允许多个auto_ptr拥有同一个指针,在c 11中已被废弃,不建议使用,应该使用unique_ptr。
scoped_ptr顾名思义,指针的有效性和作用域相关。当scoped_ptr对象离开作用域时,其析构函数被调用,析构掉其指向的对象,避免内存泄露。
shared_ptr是功能最强大,使用最普遍的智能指针了,无论怎么重视都不为过。shared_ptr才是真正实用的类似gc的智能指针,其他的智能指针大多都比较简单,不支持对象的共享,使用范围比较窄,只适用于一些简单的情况。shared_ptr顾名思义,多个shared_ptr对象可以指向同一个对象,但并不会拷贝对象,而只拷贝其指针。这时,delete对象就不能简单地直接析构对象了,否则会造成其他指针失效,成为野指针,而需要对对象进行引用计数,每当有一个shared_ptr指向这个对象,其引用计数加一;每当delete一次,其引用计数减一,当引用计数减为0时,表明没有指针指向这个对象了,此时这个对象才会真正被删除。
weak_ptr更像是shared_ptr的辅助类,weak_ptr不增加对象的引用计数,可以用来观察对象的引用情况,并在需要的时候通过weak_ptr构造shared_ptr.
想要详细地介绍智能指针应该对每种指针的原理、实现进行说明,并写些示例代码示范其用法,每种智能指针都需要专门写文章来分析,可惜一来我自己的水平也不高,二来时间和精力有限,所以只能粗浅地写一写,大概介绍一下智能指针的概念,待以后再完善补充吧。因为水平有限必然会有很多疏漏及错误,欢迎批评指正