您的位置:首页 > 其它

一个可以放入STL容器的简洁、高效、非计数的智能指针实现

2012-12-02 22:15 441 查看
只要学过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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: