您的位置:首页 > 编程语言 > C语言/C++

C++Primer中 智能指针一例分析

2013-01-26 00:46 225 查看
近期复习《C++Primer》,用的第四版。在13章复制控制中,书上给出了一个自定义智能指针的例子。代码见下,纯抄书。

关于这个例子,自己之前有个疑问,一直没能解答,就是为什么我们已经用了U_Ptr class 封装了实际使用的 int*, 在U_Ptr里面维护了一个int* 的引用计数,为啥还要再用HasPtr class 再封装一次U_Ptr? 显然这里暴露给外部使用的是HasPtr, 它才是所谓的智能指针。

class U_Ptr{
friend class HasPtr; //here only accessiable for HasPtr
int *ip;
size_t use;
U_Ptr(int *p): ip(p), use(1){}
~U_Ptr(){delete ip;}
};
class HasPtr{
public:
//HasPtr owns the pointer, p must have been allocated dynamically
HasPtr(int *p, int i): ptr(new U_Ptr(p)), val(i){}
//copy constructor
HasPtr(const HasPtr &orig):
ptr(orig.ptr), val(orig.val){++ptr->use;}
//copy assign operator
HasPtr& operator=(const HasPtr&);
~HasPtr(){
if(--ptr->use == 0)
delete ptr;
}

//other operation via *ptr
int *get_ptr() const{return ptr->ip;}
...
private:
U_Ptr *ptr;
int val;
};
这回复习重新把这段代码敲了一遍,在敲 ~HasPtr() 析构函数的时候,忽然明白了。

如果没有HasPtr()这一层,~U_Ptr()中就必须加上引用计数减1这段逻辑,并且只能在引用计数减到0时,删除原指针所指向的内存部分(这里是简单的ip)。可是,int* ip是在U_Ptr中被创建的,如果U_Ptr被析构了,那么ip肯定会被析构。

问题来了,我们希望的是,智能指针被析构时,所封装的原指针并不立刻被析构,这也正是我们费尽心思使用引用计数的原因。原指针本身的析构我们肯定是不能染指的,不管是原生类型如int*,还是 ClassA*, 对于外层的智能指针来说,必须是不可见的。

怎么办? 最简单的方式,就是再加一层封装,如这里的HasPtr。 这样我们可以控制U_Ptr的析构时间,从而将原指针的析构和内存释放推迟到没有任何一个引用存在的时候。

曾经读一本介绍内核的书时,在头一章看到一句话:软件上的任何问题,都可以通过多加一个中间层来解决。其实这里智能指针中的设计,同样沿用这个思想。

ps,实际应用中,智能指针的实现方法和思路应该有很多,比如很多框架库。C++Primer只是借这个最简单的例子,管中窥豹,这篇短博,也是如此。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: