只要学过C++的都知道STL内有一个auto_ptr的智能指针实现,可惜的很这个智能指针和STL容器格格不入,无法和像vector、list、deque、map、set等这样关键性的容器配合使用,大大降低了auto_ptr的使用范围和应用范畴。至于boost库内倒是有share_ptr和weak_ptr这样的智能指针,但是boost库并非标准库,且实现比较复杂不比auto_ptr实现简单。为此我想和很多,难道真的没有一个简单的可以放置到容器内高效的的智能指针呢?最近有机会我终于实现了一个这样一个智能指针。其原理如下:
首先,吸取auto_ptr的教训,将内存管理的句柄分为两个。一个负责持有对象,在必要时释放所持有的对象所占的空间。另一个则是负责供外面的用户使用,即使所持有的对象转移了依然不影响对源对象的使用。
接着,吸取auto_ptr之所以高效的经验,采用持有对象转移策略。
然后,将管理对象分治为管理一个对象和管理多个对象的方略,分别提供不同实现方法和操作以便更进一步降低复杂度。
最后,将接口最小化,紧守本有功能,不提供额外功能,但是在力所能及的情况下提供足够便利的高效的功能。
其具体实现代码如下:
auto_pointer.h
#ifndef __AUTO_POINTER_H__
#define __AUTO_POINTER_H__
//#include "debug_log.h"
#include <cassert>
用于代替std::auto_ptr,其接口设计与其保持兼容,用于管理单个对象
template <typename T>
class auto_pointer
{
public:
typedef T element_type;
public:
为了兼容原来的auto_ptr, 缺省构造函数
auto_pointer() throw()
: m_uPtr(0)
, m_aPtr(0)
{
}
为了兼容原来的auto_ptr,单参数构造
auto_pointer(element_type *p) throw()
: m_uPtr(p)
, m_aPtr(p)
{
}
复制构造函数
一个本类对象传过来,接收方保存其对象的句柄值,源对象不再负责释放其对象句柄
auto_pointer(const auto_pointer<element_type>& ref) throw()
: m_uPtr(release(&ref))
, m_aPtr(m_uPtr)
{
}
~auto_pointer() throw()
{
reset(0);
}
auto_pointer<element_type>& operator =(const auto_pointer<element_type>& ref) throw()
{
reset(release(&ref));
return *this;
}
const element_type& operator *() const throw()
{
assert(m_uPtr != 0);
return *m_uPtr;
}
element_type& operator *() throw()
{
assert(m_uPtr != 0);
return *m_uPtr;
}
const element_type* operator->() const throw()
{
return m_uPtr;
}
element_type* operator->() throw()
{
return m_uPtr;
}
element_type* get() const throw()
{
return m_uPtr;
}
const element_type* get() throw()
{
return m_uPtr;
}
void reset(element_type *p) throw()
{
if (m_aPtr)
{
//DEBUG_LOG("auto_pointer delete");
delete m_aPtr;
}
m_uPtr = m_aPtr = p;
}
element_type *release() throw()
{
return release(this);
}
private:
将源对象的持有句柄置空,返回源对象的使用句柄
static element_type *release(const auto_pointer<element_type> *ref) throw()
{
auto_pointer<element_type> *p = (const_cast< auto_pointer<element_type> *>(ref));
p->m_aPtr = 0;
return p->m_uPtr;
}
private:
element_type* m_uPtr;
element_type* m_aPtr;
};
template <>
class auto_pointer<void>
{
public:
typedef void element_type;
};
自动缓冲区类,是auto_pointer的多个对象版
template <typename T>
class auto_buffer
{
public:
typedef unsigned int size_t;
typedef T element_type;
public:
缺省构造器
auto_buffer() throw()
: m_uPtr(0)
, m_aPtr(0)
{
}
一般构造器
auto_buffer(element_type *p) throw()
: m_uPtr(p)
, m_aPtr(p)
{
}
复制构造器
一个本类对象传过来,接收方保存其对象的句柄值,源对象不再负责释放其对象句柄
auto_buffer(const auto_buffer<element_type>& ref) throw()
: m_uPtr(release(&ref))
, m_aPtr(m_uPtr)
{
}
析构器
~auto_buffer() throw()
{
reset(0);
}
复制操作符
auto_buffer<element_type>& operator =(const auto_buffer<element_type>& ref) throw()
{
reset(release(&ref), ref.m_size);
return *this;
}
element_type* get() throw()
{
return m_uPtr;
}
const element_type* get() const throw()
{
return m_uPtr;
}
void reset(element_type *p) throw()
{
if (m_aPtr)
{
//DEBUG_LOG("auto_buffer delete");
delete[] m_aPtr;
}
m_uPtr = m_aPtr = p;
}
element_type* release() throw()
{
return release(this);
}
private:
将源对象的持有句柄置空,返回源对象的使用句柄
static
element_type* release(const auto_buffer<element_type> *ref) throw()
{
auto_buffer<element_type> *p = (const_cast< auto_buffer<element_type> *>(ref));
p->m_aPtr = 0;
return p->m_uPtr;
}
private:
element_type* m_uPtr;
element_type* m_aPtr;
};
template <>
class auto_buffer<void>
{
public:
typedef void element_type;
};
#endif
end auto_pointer.h
debug_log.h
#ifndef __DEBUG_LOG_H_
#define __DEBUG_LOG_H_
//#include <qstring.h>
void debug_log(const char *_s);
//inline void debug_log(const QString& _s)
//{
// debug_log(_s.toLocal8Bit().constData());
//}
#ifdef ENABLE_DEBUG_LOG
#define DEBUG_LOG(a) debug_log(a)
//#define DEBUG_LOG1(a) DEBUG_LOG(QString(# a ":%1").arg(a))
//#define DEBUG_LOG2(a, b) DEBUG_LOG(QString(# a ":%1 " # b ":%2").arg(a).arg(b))
#else
#define DEBUG_LOG(a)
//#define DEBUG_LOG1(a)
//#define DEBUG_LOG2(a, b)
#endif
#endif //__DEBUG_LOG_H_
end debug_log.h
debug_log.cpp
#include "debug_log.h"
#include <cstdio>
#include <string>
#include <ctime>
//#include <cstdarg>
const std::string now_time()
{
time_t _tim = time(0);
std::string _stim(ctime(&_tim));
return _stim.substr(0, _stim.size() - 1);
}
void debug_log(const char *s)
{
FILE *_out = fopen("c:/debug_log.log", "a+");
if (_out)
{
fprintf(_out, "%s %s\n", now_time().c_str(), s);
fclose(_out);
}
}
end debug_log.cpp
main.cpp
#include "auto_pointer.h"
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
struct a
{
a(int _base = 0, const std::string& _s = "")
: base(_base)
, s(_s)
{
}
int base;
std::string s;
};
std::string to_str(int _value)
{
char buffer[256] = {0};
sprintf(buffer, "%d", _value);
return buffer;
}
int main(int argc, char *argv[])
{
/*auto_pointer<int> ap1(new int(1978));
auto_pointer<int> ap2(new int);
*ap2 = 110;
std::cout << "ap1:" << *ap1 << ", ap2:" << *ap2 << std::endl;
ap2 = ap1;
std::cout << "ap1:" << *ap1 << ", ap2:" << *ap2 << std::endl;
auto_pointer<a> p1(new a(100, "wps"));
std::cout << "base:" << p1->base << ", s:" << p1->s << std::endl;
*/
/*typedef std::vector< auto_pointer<a> > ints_t;
ints_t va;
for (int i = 0; i < 100; ++i)
{
va.push_back(new a(i, to_str(i << 1)));
}
*/
typedef auto_buffer<int> ints_t;
ints_t v(new int[100]);
int i = 0;
for (int *begin = v.get(), *end = begin + 100; begin != end; ++begin)
{
*begin = i++;
}
//int i = 0;
for (const int *begin = v.get(), *end = begin + 100; begin != end; ++begin)
{
std::cout << *begin << std::endl;
//*begin = 123;
}
typedef std::vector< auto_buffer<int> > va_t;
va_t va;
for (int i = 0; i < 10; ++i)
{
auto_buffer<int> buf(new int[10]);
for (int *begin = buf.get(), *end = begin + 10; begin != end; ++begin)
{
*begin = i;
}
va.push_back(buf);
}
return 0;
}
end main.cpp