正文

我写的智能指针auto_ptr2007-03-20 17:37:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/rickone/24137.html

分享到:

为什么要用这个auto_ptr,一般的C语言指针不够用吗?如果C++里没有new,那一般的指针就够用了,现在的代码都像这样: int *p=new int[100]; //使用p delete[] p; 使用p的时候,如果突然出了问题,比如丢出异常,就会中止程序,而不能运行delete,造成内存泄漏,所以在使用的时候,经常要做很多判断,比如 if(p){   ...   delete[] p;} if(XXX){   delete[] p;   throw(xx);} 所以,拿到内存容易,但责任就大啊,所以整个代码被整个乱七八糟,而且程序员还要保持清醒的头脑,一不小心就。。。 STL的auto_ptr就是为了解决这个问题,做的一个封装,在指针的运算过程中,比如*,->,发生错误,丢异常,并在析构的时候delete。 把VC6里的auto_ptr复制下: template<class _Ty> class auto_ptr {public: typedef _Ty element_type; explicit auto_ptr(_Ty *_P = 0) _THROW0()  : _Owns(_P != 0), _Ptr(_P) {} auto_ptr(const auto_ptr<_Ty>& _Y) _THROW0()  : _Owns(_Y._Owns), _Ptr(_Y.release()) {} auto_ptr<_Ty>& operator=(const auto_ptr<_Ty>& _Y) _THROW0()  {if (this != &_Y)   {if (_Ptr != _Y.get())    {if (_Owns)     delete _Ptr;    _Owns = _Y._Owns; }   else if (_Y._Owns)    _Owns = true;   _Ptr = _Y.release(); }  return (*this); } ~auto_ptr()  {if (_Owns)   delete _Ptr; } _Ty& operator*() const _THROW0()  {return (*get()); } _Ty *operator->() const _THROW0()  {return (get()); } _Ty *get() const _THROW0()  {return (_Ptr); } _Ty *release() const _THROW0()  {((auto_ptr<_Ty> *)this)->_Owns = false;  return (_Ptr); }private: bool _Owns; _Ty *_Ptr; }; 代码在<memory>里,写得比较丑陋,忍住胃看吧。但是它还是有问题,在《C++Primer》里写了一些注意,所以程序员还是要甚用。(听说BOOST里有完全安全的auto_ptr,不知道怎么写的) 我的程序完全是照着那些缺陷做的,是用一个map表保存堆内在的分配情况,比如一个堆上的对象指针被分发给几个auto_ptr,那只有在最后一个析构的时候去delete,怎么实现?用使用计数器,就像文件一样,把堆上的内存看成资源,资源可以被多个‘人’打开,打开一次,计数器+1,关闭一次-1,最后一个关闭的时候进行析构,另外对于数组的情况,只用做一个标记就行了。 (异常部分没写,只做个框架) #include <map>#ifndef HEAPPTR_2007#define HEAPPTR_2007 template<class T>class heap_ptr{ //enum{tag=t}; T* ptr; bool bArray; static std::map<T*,int> use_count;public: heap_ptr():ptr(0){}; heap_ptr(T* q, bool b=false){  bArray=b;  attach(q); }; ~heap_ptr(){  detach(); }; // *,->和[]运算符 T& operator*(){  return *ptr; }; T* operator->(){  return ptr; }; T& operator[](int index){  return ptr[index]; }; // 拷贝构造函数和赋值函数 heap_ptr(heap_ptr &hp){  attach(hp.ptr);  bArray=hp.bArray; }; heap_ptr& operator=(heap_ptr &hp){  detach();  attach(hp.ptr);  bArray=hp.bArray; }; // void attach(T* q){  std::map<T*,int>::iterator it=use_count.find(q);  if(it==use_count.end())  {   use_count[q]=1;  }  else  {   use_count[q]++;  }  ptr=q; }; void detach(){  if(ptr)  {   int c=--use_count[ptr];   if(c==0)   {    use_count.erase(ptr);    if(bArray)     delete[] ptr;    else     delete ptr;   }  } }; }; #define USE_HEAPPTR_ON(TYPE) \ std::map<TYPE*,int> heap_ptr<TYPE>::use_count; #endif 由于只用于堆上的动态内存,所以干脆叫heap_ptr,最后的宏是为了初始化静态成员,如果要使用某个类在堆上的内存,在使用的地方,在全局定义的位置,加上这句宏就可以了。 使用: #include "stdafx.h"#include "heapptr.h"#include <iostream>using namespace std; USE_HEAPPTR_ON(int) void foo1(heap_ptr<int> p){ *p=1;}void foo2(heap_ptr<int> p){ *p=2;}void foo3(heap_ptr<int> p){ p[0]=3;}void foo4(heap_ptr<int> p){ p[1]=4;}int main(int argc, char* argv[]){ printf("Hello World!\n"); heap_ptr<int> p(new int(0)); heap_ptr<int> q(new int[10],true); foo1(p); cout<<*p<<endl; foo2(p); cout<<*p<<endl; foo3(q); foo4(q); cout  <<q[0]<<endl  <<q[1]<<endl; return 0;}

阅读(7218) | 评论(3)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册