一个可以放入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
首先,吸取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
相关文章推荐
- 自己实现一个带引用计数的智能指针,根据源码
- 非常经典的C++ 引用计数技术及智能指针的简单实现
- 一个智能指针的实现(代码)
- 一个简单的智能指针的实现
- Ineffective C++(1):STL容器不仅仅可以保存指针
- 引用计数的智能指针的实现
- 智能指针的一个实现(没有考虑线程安全)
- 自己实现一个C++ 智能指针
- 一个简单的智能指针实现
- [转贴]从零开始学C++之STL(二):实现一个简单容器模板类Vec(模仿VC6.0 中 vector 的实现、vector 的容量capacity 增长问题)
- 利用STL算法高效实现容器的循环移位
- 带引用计数的智能指针(模板类)实现的3种方法
- 带引用计数的智能指针实现
- 智能指针(一):STL auto_ptr实现原理
- C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).
- C++ 智能指针的一个实现(基于模板和Shared_ptr)
- C++ 引用计数技术及智能指针的简单实现
- 智能指针原理,并实现一个简单的智能指针
- OSG中引用计数与智能指针实现原理
- C++智能指针,指针容器原理及简单实现(auto_ptr,scoped_ptr,ptr_vector).