智能指针与句柄类(一)

  句柄类/智能指针(smart point)是存储指向动态分配(堆)对象指针的类。除了能够在适当的时间自动删除指向的对象外,他们的工作机制很像C++的内置指针。句柄类实际上是通过复制指向引用计数器类型的指针,来代替复制实际对象;从而使得复制对象变成复制指针,实现虚拟复制(即是用复制对象的地址代替复制对象本身),以提高内存效率和访问速度。

  引用计数是复制控制成员中使用的技术,跟踪该类有多少个对象共享一个指针。引用计数与共享对象一起存储,需要创建一个单独类指向共享对象并管理引用计数。由构造函数而不是赋值构造函数设置共享对象的状态并将引用计数置为1,每次有复制构造函数或赋值操作符生成新的副本时,引用计数加1,由析构函数撤销对象或作为赋值操作符的左操作数撤销对象时,引用计数减1,赋值操作符和析构函数对引用计数进行判断是否为0,如果是,则撤销对象。

  通用的句柄类模板实现如下(摘自《C++ Primer》):

 1 template<class T> class Handle
 2 {
 3 public:
 4     Handle(T *p = 0):ptr(p), use(new size_t(1)){}
 5     T& operator*();
 6     T* operator->();
 7
 8     const T& operator*()const;
 9     const T* operator->()const;
10
11     Handle(const Handle& h):ptr(h.ptr), use(h.use)
12     { ++*use; }
13
14     Handle& operator=(const Handle&);
15     ~Handle() { rem_ref(); }
16
17 private:
18     T* ptr;            //shared object
19     size_t *use;    //count of how many Handles spoint to *ptr
20     void rem_ref()
21     {
22         if(--*use == 0)
23         {
24             delete ptr;
25             delete use;
26         }
27     }
28 };
29
30 template<class T>
31 inline Handle<T>& Handle<T>::operator=(const Handle &rhs)
32 {
33     ++*rhs.use;        //protect against self-assignment
34     rem_ref();        //decrement use count and delete pointers if needed
35     ptr = rhs.ptr;
36     use = rhs.use;
37
38     return *this;
39 }
40
41 template<class T>
42 inline T& Handle<T>::operator*()
43 {
44     if(ptr) return *ptr;
45     throw std::runtime_error
46         ("dereference of unbound Handle");
47 }
48
49 template<class T>
50 inline T* Handle<T>::operator->()
51 {
52     if(ptr) return ptr;
53     throw std::runtime_error
54         ("access through of unbound Handle");
55 }
56
57 template<class T>
58 inline const T& Handle<T>::operator*()const
59 {
60     if(ptr) return *ptr;
61     throw std::runtime_error
62         ("dereference of unbound Handle");
63 }
64
65 template<class T>
66 inline const T* Handle<T>::operator->()const
67 {
68     if(ptr) return ptr;
69     throw std::runtime_error
70         ("access through of unbound Handle");
71 }

使用句柄类的例子:

 1 int main()
 2 {
 3     Handle<int> hp(new int(42));
 4     {
 5         //new scope
 6         Handle<int> hp2 = hp;
 7         cout<<*hp<<"  "<<*hp2<<endl;
 8         *hp2 = 10;
 9     }
10     cout<<*hp<<endl;
11     return 0;
12 }

代码line6使用hp构造了新的Handle对象hp2,二者指向同一块内存。line8对*hp2重新赋值,此时二者指向内存值由42变为10,退出new scope后,hp2对象析构,但引用计数值未减小到0,line10输出*hp的值,由于二者指向内存空间相同,所以此处输出10,之前的42被覆盖,退出main函数时,引用计数减小到0,此时hp析构函数将构造时分配的空间delete。

  可以看出,上面展示的句柄类可以完成动态分配指针的托管,并且高效完成复制与赋值操作。但是在改变*hp2时,hp托管的对象值同样改变了,这可能会违背开发人员的意愿,毕竟hp和hp2是两个对象。在更改hp2时,要做到防止hp托管对象被改变,那么句柄类需要自动复制对象并与原对象断开,这被称为写时复制(copy-on-write)。

  未完待续……

时间: 2024-10-11 13:36:31

智能指针与句柄类(一)的相关文章

智能指针与句柄类(四)

当我们希望使用容器来保存继承体系中的对象时,容器用于继承体系中的类型会有影响:派生类对象复制到基类对象时,派生类对象将被切掉.那么解决这一问题的方法通常是使用容器保存基类对象的指针,这些指针实际指向的是程序运行时动态分配的派生类对象,用户必须保证在容器析构前调用delete来释放动态分配的对象,如下例: 1 class Base 2 { 3 public: 4 virtual void action() = 0; 5 }; 6 class Derived1 : public Base 7 {..

智能指针与句柄类(二)

之前文章提到写时复制(copy-on-write)技术,要实现这种功能,针对上文中Handle代码,需要将size_t * use这个抽象出来,封装成一个引用计数类,提供写时复制功能.CUseCount类实现如下: 1 class CUseCount 2 { 3 public: 4 CUseCount(); 5 CUseCount(const CUseCount&); 6 ~CUseCount(); 7 8 bool only()const; //判断引用计数是否为0, 句柄类无法访问priva

智能指针与句柄类(三)

之前文章中实现的写时复制,句柄类中引用计数和T类型指针是分开的,这里换一种方式来处理,将引用计数和T类型指针视为一个整体,当做句柄类模板参数.先对上节中的引用计数进行改造: 1 class CUseCount 2 { 3 public: 4 CUseCount(); 5 CUseCount(const CUseCount&); 6 CUseCount& operator=(const CUseCount&); 7 ~CUseCount(); 8 9 void markUnshare

C++中智能指针的模板类

在C++中,智能指针是一个非常重要的概念.因为C++的类动态分配的对象不能自动释放掉,需手动调用new运算符.当程序员大意时,或程序发生异常时,或许就会发生没有手动释放内存而造成内存泄露. 智能指针的定义:就是在一个类中,存在一个指向另一个类对象的指针,并通过对指针运算符(比如:->,*)的重载,就可以实现利用当前类的对象通过指针运算符来操纵另一个类的成员(就像另一个类的指针操作一样),并且,在析构函数中定义了delete操作,借助于变量的作用域,能够实现类对象空间的自动释放. 在C++ 11中

C/C++——跟我重写智能指针auto_ptr模版类

第一次使用auto_ptr的时候感觉很好用,但是对内部原理根本不懂,心里不知道这东西到底是个什么东东,总是感觉这东东比较陌生.今天有时间来简单实现一下该类模版auto_ptr,实现了该模版类的主要功能,可以让大家了解一下这个东东内部到底是个什么情况. 栈对象和堆对象的区别: 首先,看一下两种类对象的区别,一个是在栈上分配空间,另一个是在堆上分配空间. 如果看到这里,你不清楚堆和栈的区别.那我也不解释了,自行Google..(如果你想baidu也不拦你) 1.先测试栈上分配的对象 #include

【C++】智能指针类和OpenCV的Ptr模板类

智能指针类 引用计数 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象.引用计数为0时,删除对象. 其基本使用规则是: 每次创建类的新对象时,初始化指针并将引用计数置为1.当对象作为另一对象的副本而创建时,复制构造函数复制指针并增加与之相应的引用计数的值.对一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数的值(如果引用计数减至0,则删除对

C++ 句柄类

一.容器与继承 在容器中保存有继承关系的对象时,如果定义成保存基类对象,则派生类将被切割,如果定义成保存派生类对象,则保存基类对象又成问题(基类对象将被强制转换成派生类对象,而派生类中定义的成员未被初始化).     唯一的可行的选择是容器中保存对象的指针.但是需要用户管理对象和指针.C++中一个通用的技术是包装类(cover)或句柄类(handle).用句柄类存储和管理类指针. 句柄类大体上完成两方面的工作: 管理指针,这与智能指针的功能类似. 实现多态,利用动态绑定,是得指针既可以指向基类,

C++单线程智能指针实现

阅读目录 1.智能指针是什么 2.普通指针存在的问题 3.什么是引用计数 4.智能指针实现 4.1.基础对象类 4.2.辅助类 4.3.为基础对象类实现智能指针类 4.4.智能指针类的使用与测试 5.智能指针类的改进一 6.智能指针改进二 正文 文章也发布在 腾讯云+社区 一直以来都对智能指针一知半解,看C++Primer中也讲的不够清晰明白(大概是我功力不够吧).最近花了点时间认真看了智能指针,特地来写这篇文章. 回到顶部 1.智能指针是什么 简单来说,智能指针是一个类,它对普通指针进行封装,

智能指针 与 oc中的指针

智能指针 与 oc中的指针 智能指针的原理及实现 当类中有指针成员时,一般有两种方式来管理指针成员:一是采用值型的方式管理,每个类对象都保留一份指针指向的对象的拷贝:另一种更优雅的方式是使用智能指针,从而实现指针指向的对象的共享. 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count).智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针. 每次创建类的新对象时,初始化指针并将引用计数置为1:当对象作为另一对象的副