为什么要用这个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;
}
评论