文章目录
浅谈智能指针
一、概述
1.智能指针的分类
1.auto_ptr
2.unique_ptr
3.shared_ptr
2.智能指针的作用
若使用智能指针来管理堆内存的空间,那么在包含堆内存分配语句的代码块结束时,会自动调用智能指针的析构函数来对分配的内存进行释放,大大提高了代码的安全性,降低了编码复杂度。
二、智能指针创建对象
1.语法
1.auto_ptr<type> ap(new type(value));
2.unique_ptr<type> ap(new type(value));
3.shared_ptr<type> ap(new type(value));
2.为什么能如此创建对象
我们从源代码来剖析:
template<class T>
class auto_ptr{
private:
T*ap;
public:
explicit auto_ptr(T* ptr=0) :ap(ptr){
}
………………
}
auto_ptr<type> ap(new type(value));
这里面的 new type(value)返回了一个临时对象的地址,然后调用auto_ptr将返回的地址保存进auto模板类对应的type类型的指针之中。
说明explicit
auto_ptr 的构造函数前面使用了explicit ,这就告诉编译器,我不接受隐式类型转换,也就是,我们不能将一个常规指针通过隐式类型转换变为auto_ptr类型的智能指针。
一个常规指针想要作为智能指针的构造函数的参数,就需要如下示例的方法:
auto_ptr<double> ap;
double *p=new double;
ap=p; //这是不被允许的,因为auto_ptr的构造函数声明为了explicit,不可以进行隐式的类型转换
//如果有不明白这种赋值操作为什么和构造函数有关的话,可以再去回顾一下构造函数的知识。
ap=auto_ptr<double>(p); //这是允许的,允许显示的类型转换
三、智能指针内存管理原理
1.源码分析
template<class T>
class auto_ptr{
private:
T*ap;
public:
………………
~auto_ptr()throw()
{
delete ap;
}
………………
}
在auto_ptr对象消解时,会调用他的析构函数,就将该对象中的指针ap指向的内存销毁掉了。
但是将一个常规指针转换为智能指针依旧是不安全的,即使是使用了显式类型转换,因为两个指针仍然会指向同一块内存。
四、智能指针的特性
先看一段代码:
auto_ptr<string> ps (new string("i"));
auto_ptr<string> vocation;
vocation=ps;
这种情况在某些时候是安全的,但是某些时候是不安全的,我们稍后会提到
1.所有权概念(auto_ptr和unique_ptr)
对于特定的对象,只有一个智能指针可以拥有它,这样只有拥有对象的智能指针的构造函数会删除该对象,然后,让赋值操作转移所有权。这样做就防止了两个指针指向同一块内存然后重复释放空间的问题。auto_ptr和unique_ptr都是如此,但是unique_ptr更加严格。
接下来我们会在智能指针的区别讨论这一点。
2.创建智能更高的指针(shared_ptr)
创建智能更高的指针,跟踪引用特定对象的智能指针数。称为引用计数。例如,赋值时,计数加一,指针过期时,计数减一。当最后一个指针过期时,也就是计数为0时,调用delete。
五、auto_ptr和unique_ptr的区别
前面我们提到了,他们两个都有所有权概念的特性,那么这两种指针的区别在哪里呢?
unique_ptr相比于前者更加的安全,因为它将以下代码视为非法,编译阶段就会报错
unique_ptr<string> p1(new string("ll"));
unique_ptr<string> p2;
p2=p1;
1.视为非法的原因
p1在给p2赋值后,会置空,或者说不再指向有效数据。此时如果
cout<<*p1<<endl;
执行这样的指令,会出现严重的运行时错误。但是由于unique_str编译时就会出错,那么就很好的避免了这个问题。
2.特殊情况下允许这种赋值
unique_ptr<string> demo(const char*s){
unique_str<string> temp(new string(s));
return temp;
}
unique_ptr<string> ps;
ps=demo("special");
允许这种赋值的原因:
因为临时的unique_ptr对象会很快被销毁,没有机会用它来访问无效的数据。
而auto_ptr会允许unique_ptr视为非法的赋值,这是不安全的,所以,我们一般可以把auto_ptr舍弃。
六、unique_ptr的特殊地方
unique_ptr可以释放数组空间,其他两种指针都不可以。
七、解析所有权转移的原理
1.源代码分析
auto_ptr& operator=(auto_ptr&rhs)throw()
{
reset(rhs.release());
return*this;
}
release()函数,是将智能指针所持有的指针释放,然后返回所有权
reset()函数的参数是智能指针要指向的新的对象,如果里面的参数指针指向的对象不是空的,那么将删除原来管理的对象。
最后返回新的auto_ptr的对象。
接下来调用拷贝构造函数,将新的对象拷贝给auto_ptr的对象
auto_ptr(auto_ptr& rhs)throw():ap(rhs.release())
{
}
————————————————————
The End~~~~