大龙的博客

常用链接

统计

最新评论

智能指针重载operator ->()、自赋值、引用计数 -- 转

智能指针(smart pointers),是一种加限制的近委托机制(相当于老师的管理),其中包含普通指针(相当于学生的自主)。它将指针对象化,返回X类指针控制X类型对象(通常显式含有一个X类型指针成员);优点在于X类指针成员共享内存分配,可防悬挂,采用引用计数,无指针指向时才析构。

当然,也可在定义拷贝赋值时分配新存储空间,使不共享,就完全无此问题。但此时需重定义分配内存的构造函数与拷贝构造函数,对赋值函数不需改变,也无须检测自赋值(因为没有delete语句)。e.g.:

       class String{                 //上级管理类,物业!

struct Srep;                  //包含类的声明

Srep *rep;                    //内含普通类指针,被管理

Srep * operator->();             //返回Srep指针

//……

}

重载operator->(),返回普通对象指针,称为间接(Dereferencing),可形成“智能指针”机制。这样方便操作,也可不用。对于Invoker->member;,operator ->为一元后缀运算符,可作两种解释:

①Invoker为指针,将寻找紧随其后的类成员(或函数)标识符,找不到就出错,这也是最常见的用法。

②Invoker为(定义的智能指针)对象,将解释为(Invoker.operator->())->member。若Invoker类未重载operator->()则出错;重载了X operator ->()时,如果返回类型X为指针,则进入①状态;如果返回值类型仍为对象,再进入②状态,判断是否可循环。

返回值应该为两种:①指针,并找到成员标志符;②定义了operator->()的对象,将循环迭代。否则出错。具体示例见于《C++ Primer》14.6节与《C++ Programming Language》11.10章节。迭代器就是一个很好的佐证,如vector<int> vec;中,定义了vector::iterator,返回值的指针类型为int。即有(*vec.begin())为int型。

自赋值的危害:可参考《廿六、赋值函数重载与拷贝构造函数(百度百科ZT)》

=运算符(assignment)为其左操作数配置新动态资源(free store)前,通常先将原先的动态资源析构,以防止内存泄漏(现在不释放,以后就没机会了)。如为自赋值,将丢失这部分信息,造成指针挂起。需检查是否为自赋值,如果是就返回*this;否则,释放原有资源,以获得新资源!

通常用检测其指针是否相等即可(比较this与新值的指针,而非它们指向的值)。e.g.:

A operator=(const A &Other){if(this==&Other) return *this;} //不是if(*this == other)

智能指针采用引用计数(reference cout)来决定是否析构共享,常定义于受管理类中。《C++ Primer》对引用计数的描述:每次创建类的新对象时,初始化指针并将使用计数置为1。当对象作为另一对象的副本而创建时,复制构造函数复制指针并增加与之相应的使用计数的值。对一个对象进行赋值时,赋值操作符减少左操作数所指对象的使用计数的值(如果使用计数减至0,则删除对象),并增加右操作数所指对象的使用计数的值。(反过来说更好)最后,调用析构函数时,析构函数减少使用计数的值,如果计数减至0,则删除基础对象。

拷贝赋值时,常先增加右操作数计数,再减少左操作数计数,并判断删除动态存储。可防止自身赋值,如为自赋值,引用计数肯定非0,相当于加1后立即减1,不会错删;反之可能出--n=0。《C++ Primer》13.5.1与《C++程序设计》11.12节均采用的此种方法。

posted on 2010-05-08 12:29 大龙 阅读(1218) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理