当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝;另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享。那么智能指针是什么呢?智能指针是存储指向动态分配(堆)对象指针的类。
很多人都以为智能指针是一个指针,但其实它是一个模板,它可以自动释放所指向的对象。我们来看一下:
1. Auto_ptr
auto_ptr在STL中早就存在了,auto_ptr是通过权限转移的方式来防止值拷贝所带来
的问题,所谓权限转移就是说开辟的动态内存任何时刻只能由一个指针指向。
#include<iostream>
using namespacestd;
template <classT>
class Auto_ptr {
private:
T *ptr;
public:
Auto_ptr(T *p)
:ptr(p)
{}
~Auto_ptr()
{
delete ptr;
}
};
void main()
{
Auto_ptr<int> p(new int(1));
Auto_ptr<int> p1(new int(1));
p1 = p;
}
在主函数中,我们使p1=p,可以发现它出现了bug,这是因为Auto_ptr是支持复制的,但是两个Auto_ptr都包括了一个指针,当它们析构的时候,同一个指针就会被析构两次,当然会出现问题。我们应该怎样解决呢?再来看:
#include<iostream>
using namespacestd;
template<class T>
class Auto_ptr{
private:
T *ptr;
bool owner;
public:
Auto_ptr(T *p)
:ptr(p),owner(true)
{}
~Auto_ptr()
{
if (owner)
{
delete ptr;
}
}
Auto_ptr(Auto_ptr &p)
{
ptr = p.ptr;
owner = p.owner;
p.owner = false;
}
Auto_ptr &operator=(Auto_ptr &p)
{
if (this != &p)
{
if (owner)
{
delete ptr;
}
ptr = p.ptr;
owner = p.owner;
p.owner = false;
}
delete p;
return this;
}
};
voidmain()
{
Auto_ptr<int> p(new int(1));
Auto_ptr<int> p1(p);
}
为了防止拷贝,又引入了scoped_ptr,就是把拷贝构造函数在private中定义,或者只在public中声明,但不写它的定义,意思就是使其不能拷贝。
为了更方便,我们又引入了shared_ptr,它的思想就是“引用计数”,每次有一个shared_ptr关联到某个对象上时,计数值就加上1;相反,每次有一个shared_ptr析构时,相应的计数值就减去1。当计数值减为0的时候,就执行对象的析构函数,此时该对象才真正被析构!
#include<iostream>
using namespace std;
template <class T>
class Shared_ptr {
private:
T*ptr;
int*count;
public:
Shared_ptr(T*p)
:ptr(p),count(new int(1))
{}
Shared_ptr(Shared_ptr&p)
:ptr(p.ptr)
,count(p.count)
{
++(*count);
}
~Shared_ptr()
{
if(!(--(*count)))
{
deleteptr;
deletecount;
ptr= NULL;
count= NULL;
cout<< "~Shared_ptr()" << endl;
}
}
Shared_ptr&operator=(Shared_ptr &p)
{
if(ptr != p.ptr)//不能用this!=&p判断,因为有可能是多个指向相同的空间的指针进行的赋值
{
if((*count) == 1)
{
deleteptr;
deletecount;
}
ptr= p.ptr;
count= p.count;
++(*count);
}
returnthis;
}
};
struct BB {
intdata;
Shared_ptr<BB>next;
Shared_ptr<BB>pre;
BB()
:data(0)
,next(NULL)
,pre(NULL)
{}
};
void main()
{
Shared_ptr<BB>p(newBB());
Shared_ptr<BB>p1(new BB());
}
这个结果就是:
~Shared_ptr()
~Shared_ptr()
~Shared_ptr()
~Shared_ptr()
~Shared_ptr()
~Shared_ptr()
为什么会析构六次呢,我们来画个图看一下
如果把主函数的两行代码改成
p->next = p1;
p1->pre = p;
就会得到:
~Shared_ptr()
~Shared_ptr()
这是为什么呢?
因为Shared_ptr(强引用)不能循环引用,所以又引入了Weak_ptr(弱引用)
template <class T>
class Weak_ptr {
private:
T*ptr;
public:
Weak_ptr(T*p)
:ptr(p)
{}
~Weak_ptr()
{
deleteptr;
}
Weak_ptr&opreator = (Shared_ptr<T> &p)
{
ptr= p.ptr;
return*this;
}
}
*在使用的时候必须将Weal_ptr声明为Shared_ptr的友元类。
看一下仿函数:
#include<iostream>
using namespace std;
struct com {
booloperator()(int a, int b)
{
return(a > b);
}
};
int main()
{
comc;
cout<< c(1, 2) << endl;
}
我们可以使用仿函数来定制删除器:
#include<iostream>
using namespace std;
//普通删除器
struct Del {
voidoperator()(void *p)
{
deletep;
}
};
//文件删除器
struct Del2 {
voidoperator()(FILE *p)
{
fclose(p);
}
};
再来看一下拷贝
就这么多咯。(*^▽^*)