通过引用计数解决野指针的问题(C&C++)
来源:互联网 发布:php类库有哪些 编辑:程序博客网 时间:2024/05/18 11:31
C/C++代码中,野指针问题历来已久,当然,大家都知道new/delete要成对出现:
A *p = new A();delete p;p = NULL;
然而现实中却并不是总是如此简单,考虑如下例子:
class A{public: C() {} virtual ~C() {}};class B{public: B() { m_pA = NULL; } virtual ~B() {} void SetA(A* p) { m_pA = p; }private: A* m_pA;};A* pA = new A();B* pB = new B();pB->SetA(pA);delete pA;pA = NULL;//此时B中的m_pA已经无效,但是m_pA仍然不等于NULL,所以用 != NULL来判断不会有任何作用
简单来说,即pA被赋值为NULL,对B中的m_pA没有产生影响,那么怎么才能产生影响呢?
我们有两个做法:
第一种,在A的析构函数里面去B.SetA(NULL),但是这个相当于A去操作了B的数据,这是不合理的。而且当外面的指针非常多的时候,也根本不可能实现。
第二种方法呢?是的,我们可以用二级指针。
考虑如下代码:
class A{public: C() {} virtual ~C() {}};class B{public: B() { m_ppA = NULL; } virtual ~B() {} void SetA(A** pp) { m_ppA = pp; }private: A** m_ppA;};A** ppA = new (A*)();(*ppA) = new A();B* pB = new B();pB->SetA(ppA);delete (*ppA);(*ppA) = NULL;//这个时候,B中的m_ppA也会收到影响,即*m_ppA == NULL
这样确实可以解决野指针的问题,但是同时也引入了另一个问题,那就是ppA本身该什么时候释放呢?答案是:当最后一个引用ppA的类释放掉的时候。
最后一个,对,我们可以使用引用计数!
OK,正式放出我们的代码,其中使用了引用计数来确定当最后一个类释放掉的时候,ppA指针的内存被析构:
/*=============================================================================## FileName: ptr_proxy.h# Desc: 这个类的作用,就是为了解决互指指针,不知道对方已经析构的问题## Author: dantezhu#Email: zny2008@gmail.com# HomePage: http://www.vimer.cn## Created: 2011-06-13 15:24:12# Version: 0.0.1# History:# 0.0.1 | dantezhu | 2011-06-13 15:24:12 | initialization#=============================================================================*/#ifndef __PTR_PROXY_H__#define __PTR_PROXY_H__#include #include #include #include #include #include #include #include #include #include #include
我们来写段测试代码测试一下:
#include #include #include #include #include #include #include #include #include #include #include{ public: A() {} virtual ~A() {} }; class B : public IPtrProxy { public: B() {} virtual ~B() {} void print() { printf(\"this is print\\\\n\"); } void SetAPtr(const ptr_proxy& pptr) { m_ptr_a = pptr; } void check() { if (m_ptr_a.is_null()) { printf(\"is null\\\\n\"); } else { printf(\"is not null\\\\n\"); } } ptr_proxy m_ptr_a; }; int main(int argc, char **argv) { A* a = new A(); B* b = new B(); b->SetAPtr(a->get_ptr_proxy()); delete a; b->check(); b->get_ptr_proxy().true_ptr()->print(); delete b; return 0; }
输出为:
is nullthis is print
这个类最有效的使用场景是当出现大量互指指针时,那么指向对象的指针有效性判断就尤其重要,而这个类可以完美解决这个问题。
可能想的比较深的朋友会问,既然引用计数都已经用上了,那么为什么不直接通过引用计数来析构呢?
其实这几天我也在尝试,C++是否能引入完美的引用计数进行对象管理,而最终卡在一个地方,即:
如果,在类的构造函数里面,需要将引用计数对象构造出来,那么引用计数就会出现问题,如:
class A{public: A() { Count t(this); } virtual ~A() {}};Count c = new A();
这个时候就会出现问题,除非把Count构造的计数对象放到一个对象池中管理,但是又会增加对象查找的成本,所以最终放弃了这个想法。
另外一点就是,C/C++的指针在很多情况下是最方便的,过度的封装很可能会弄巧成拙,所以适度就好。
OK,惯例代码还是放到googlecode上:
http://code.google.com/p/vimercode/source/browse/#svn%2Ftrunk%2Fptr_proxy
- 本文来自:Linux学习网
- 通过引用计数解决野指针的问题(C&C++)
- 【C++】智能指针之引用计数的实现
- object c 循环引用计数问题,非常重要。
- 【C/C++】关于引用和指针的问题
- objective-c 引用计数
- Effective c++:引用计数
- 【c++】引用计数
- Objective-C 引用计数
- 【C++】引用计数
- C语言通过指针引用数组
- C通过指针引用数组元素
- C语言通过指针引用数组
- Objective C 中NSNumber的引用计数
- Object-C 关于引用计数的说明
- objective-c 的引用计数管理
- 智能指针引用计数问题
- [C] 指针参数的引用
- c/c++指针的引用
- spring 3 中使用注解的方式来进行任务调度。
- GitHub 优秀的 Android 开源项目
- STL系列(3):List 双向链表
- 1.IBAction 、IBOutlet 、Bundle identifier、退出键盘、UITextfield
- freemarker常见语法大全
- 通过引用计数解决野指针的问题(C&C++)
- FMS3系列(五):通过FMS实现时时视频聊天(Flash|Flex)
- Mac OS X 上干净卸载软件
- Linux makefile 教程 非常详细,且易懂
- 两种方法删除NSUserDefaults所有记录
- Myecliose 下如何注册dtd文件
- FMS3系列(六):使用远程共享对象(SharedObject)实现多人时时在线聊天(Flex | Flash)
- Location服务之LocationManager
- iscroll5 checkbox点击不起作用