鱼C论坛

 找回密码
 立即注册
查看: 1943|回复: 2

[技术交流] 简单的allocator应用

[复制链接]
发表于 2014-3-3 23:46:02 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 andalousie 于 2014-3-31 00:10 编辑

前些日子,我曾经在数据结构与算法板块发表过一篇来,大家看一个单链表~ 推荐,因为内存分配方式很独特哦~里面用到了简单的allocator,我习惯叫她空间配置器。那么这几天我把它略微泛化了一下,用到了上面那篇文章里面和我以前写过自己的str.h里面都还可以。大家可以对比一下和原来两篇文章里面的不同。
首先是链表的代码。
allocator.h
  1. #if !defined (BASE_ALLOCATOR)
  2. #define BASE_ALLOCATOR
  3. #include <cstddef>
  4. #include <new>

  5. template<typename T>
  6. class Allocator
  7. {
  8.         enum { BlockLinks = 4 }; // small value for testing
  9.         class Block
  10.         {
  11.         public:
  12.                 Block (Block * next): _next (next) {}
  13.                 Block * Next () { return _next; }
  14.         private:
  15.                 Block * _next;
  16.         };
  17. public:
  18.         typedef T value_type;
  19.         typedef value_type* pointer;
  20.         class Pool
  21.         {
  22.         public:
  23.                 Pool (Pool * next): _next (next) {}
  24.                 pointer val;
  25.                 Pool * _next;
  26.         };

  27.         Allocator ()
  28.                 : _blocks (0), _size(BlockLinks * sizeof(value_type)) {}
  29.         ~Allocator () { deallocate (); }
  30.         void deallocate ();
  31.         void * allocate ();
  32.         void recycle (void * mem);
  33. private:
  34.         Block * _blocks;
  35.         Pool  * _p;
  36.         size_t   _size;
  37. };

  38. template<typename T>
  39. inline void * Allocator<T>::allocate ()
  40. {
  41.         if (_p == 0)
  42.         {
  43.                 // use global operator new to allocate a block of links
  44.                 char * p = ::new char [sizeof (Block) + BlockLinks * sizeof (List::Link)];
  45.                 // add it to the list of blocks
  46.                 Block * block = ::new (p) Block (_blocks);
  47.                 _blocks = block;
  48.                 // add it to the list of links
  49.                 p += sizeof (Block);
  50.                 for (int i = 0; i < BlockLinks; ++i)
  51.                 {
  52.                         Pool * link = ::new (p) Pool (_p);
  53.                         _p = link;
  54.                         p += sizeof (Pool);
  55.                 }
  56.         }
  57.         void * mem = _p;
  58.         _p = _p->_next;
  59.         return mem;
  60. }

  61. template<typename T>
  62. inline void Allocator<T>::deallocate ()
  63. {
  64.         while (_blocks != 0)
  65.         {
  66.                 // it was allocated as an array of char
  67.                 char * mem = reinterpret_cast<char *> (_blocks);
  68.                 _blocks = _blocks->Next();
  69.                 ::delete [] mem;
  70.         }
  71. }

  72. template<typename T>
  73. inline void Allocator<T>::recycle(void * mem)
  74. {
  75.         Pool * link = static_cast<Pool *> (mem);
  76.         link->_next = _p;
  77.         _p = link;
  78. }
  79. #endif
复制代码
List.h //去掉了原来的List.cpp实现文件
  1. #if !defined (LIST_H)
  2. #define LIST_H
  3. #include <new>
  4. #include <cassert>
  5. #include "allocator.h"

  6. /*** Add this on VC6.0 */
  7. namespace std
  8. {
  9.         using ::size_t;
  10. }

  11. class List
  12. {
  13. public:
  14.         List ();
  15.         ~List ();
  16.         void insert (int value);
  17.         List* del_front ();
  18.         void merge (List& x);
  19.         void swap (List& x);
  20.         int  size () { return _size; }
  21.         bool isEmpty() const { return !_pHead; } // conversion to bool
  22. public:
  23.         class Link
  24.         {
  25.         public:
  26.                 Link (Link* pNext, int value = -1)
  27.                         : _pNext (pNext), _value (value) {}
  28.                 Link *  Next () const { return _pNext; }
  29.                 void        SetNext (Link * next) { _pNext = next; }
  30.                 int     GetValue () const { return _value; }
  31.                 // allocator
  32.                 void * operator new (std::size_t size);
  33.                 void   operator delete (void * mem);
  34.                 static void Purge ();
  35.         private:
  36.                 static Allocator<Link> _linkAlloc;
  37.                
  38.                 Link *  _pNext;
  39.                 int                _value;
  40.         };
  41. public:
  42.         class iterator
  43.         {
  44.                 friend class List;
  45.         public:
  46.                 void      operator =  (const iterator& it) { _pLink = it._pLink; }
  47.                 bool      operator == (const iterator& it) { return _pLink == it._pLink; }
  48.                 bool      operator != (const iterator& it) { return _pLink != it._pLink; }
  49.                 iterator& operator ++ () { _pLink = _pLink->Next (); return *this; }
  50.                 int       operator *  () const { return _pLink->GetValue (); }
  51.                
  52.                 iterator  operator + (std::size_t n)
  53.                 {
  54.                         iterator tmp = *this;
  55.                         while(n--) ++tmp;
  56.                         return tmp;
  57.                 }

  58.                 iterator (Link * p = 0)
  59.                         : _pLink (p) {}
  60.                 iterator (const iterator& it)
  61.                         : _pLink (it._pLink) {}
  62.         protected:
  63.                 Link * _pLink; // current link
  64.         };

  65.         friend class iterator;
  66.         iterator begin () { return iterator (_pHead); }
  67.         iterator end   () { return iterator (0); }
  68. private:
  69.         List::Link const * GetHead () const { return _pHead; }
  70.        
  71.         List::Link * _pHead;
  72.         int    _size;
  73. };

  74. /** Implementations */
  75. Allocator<List::Link> List::Link::_linkAlloc;

  76. void * List::Link::operator new (std::size_t size)
  77. {
  78.         assert (size == sizeof (Link));
  79.         return _linkAlloc.allocate ();
  80. }

  81. void List::Link::operator delete (void * mem)
  82. {
  83.         if (mem)
  84.                 _linkAlloc.recycle (mem);
  85. }

  86. void List::Link::Purge () { _linkAlloc.deallocate (); }

  87. // List

  88. List::List ()
  89.         : _pHead (0), _size(0)
  90. {}

  91. List::~List ()
  92. {
  93.         while ( _pHead != 0 )
  94.         {
  95.                 Link * pLink = _pHead;
  96.                 _pHead = _pHead->Next (); // unlink pLink
  97.                 delete pLink;
  98.         }
  99. }

  100. void List::insert (int value)
  101. {
  102.         Link * pLink = new Link (_pHead, value);
  103.         _pHead = pLink;
  104.         _size++;
  105. }

  106. List* List::del_front ()
  107. {
  108.         List * tmp = new List;
  109.         tmp->_pHead = _pHead;
  110.         _pHead = _pHead->Next ();
  111.         // don't delete recursively!
  112.         tmp->_pHead->SetNext(0);
  113.         tmp->_size = 1;
  114.         return tmp;
  115. }

  116. void List::swap (List& x)
  117. {
  118.         List::Link * tmp = _pHead;
  119.         _pHead = x._pHead;
  120.         x._pHead = tmp;
  121.        
  122.         int tmpsize = _size;
  123.         _size = x._size;
  124.         x._size = tmpsize;
  125. }

  126. void List::merge (List& x)
  127. {
  128.         iterator f1 = begin(); iterator l1 = end();
  129.         iterator f2 = x.begin(); iterator l2 = x.end();
  130.        
  131.         iterator prev;
  132.         while(f1 != l1 && f2 != l2)
  133.         {
  134.                 if(*f2 <= *f1)
  135.                 {
  136.                         iterator next = f2;
  137.                         ++next;
  138.                         if(!prev._pLink)
  139.                         {
  140.                                 _pHead = f2._pLink;
  141.                                 f2._pLink->SetNext (f1._pLink);
  142.                         }
  143.                         else
  144.                         {
  145.                                 prev._pLink->SetNext (f2._pLink);
  146.                                 f2._pLink->SetNext (f1._pLink);
  147.                         }
  148.                         prev = f2;
  149.                         f2 = next;
  150.                 }
  151.                 else
  152.                 {
  153.                         prev = f1;
  154.                         ++f1;
  155.                 }
  156.         }
  157.         if(f2 != l2)
  158.                 prev._pLink->SetNext (f2._pLink);
  159.        
  160.         _size += x._size; x._size = 0;
  161. }

  162. #endif
复制代码

然后搬出我最新修改的str.h头文件,是实现自己的string的。
str.h
  1. #ifndef STD_STRING
  2. #define STD_STRING

  3. #include "ios.h"
  4. #include <string.h>

  5. void memmove(char *dest, char *src, size_t n)
  6. {
  7.     /* No need to do that thing. */
  8.     if (dest == src)
  9.         return;

  10.     /* Check for destructive overlap.  */
  11.     if (src < dest && dest < src + n) {
  12.         /* Destructive overlap ... have to copy backwards.  */
  13.         src += n;
  14.         dest += n;
  15.         while (n-- > 0)
  16.             *--dest = *--src;
  17.     } else {
  18.         /* Do an ascending copy.  */
  19.         while (n-- > 0)
  20.             *dest++ = *src++;
  21.     }
  22. }

  23. template <class T>
  24.   void swap (T &a, T &b)
  25. {
  26.   T tmp = a;
  27.   a = b;
  28.   b = tmp;
  29. }

  30. template <class Iterator>
  31.   void reverse (Iterator first, Iterator last)
  32. {
  33.   while ((first!=last)&&(first!=--last)) {
  34.     swap(*first, *last);
  35.     ++first;
  36.   }
  37. }

  38. class out_of_range{
  39. public:
  40.         out_of_range()
  41.         {
  42.                 std::cerr << "Error: Invalid access of element. " << std::endl;
  43.         }
  44. };

  45. namespace std{
  46.         class string{
  47.         public:
  48.                 typedef size_t        size_type;
  49.                 typedef char          value_type;
  50.                 typedef const string& const_reference;
  51.                 typedef const char *  const_pointer;
  52.                 typedef value_type *  iterator;

  53.         private:
  54.                 class str_allocator
  55.                 {
  56.                         struct free
  57.                         {
  58.                                 char * val;
  59.                                 free *_next;
  60.                         };
  61.                 public:
  62.                         str_allocator () : _p (0) {}
  63.                         ~str_allocator () { deallocate(); }
  64.                         void deallocate();
  65.                         void * allocate();
  66.                         void recycle (void * link);
  67.                 private:
  68.                         free * _p;
  69.                 };
  70.                
  71.         public:
  72.             string(const_pointer str = "");                 //default constructor(value_type)
  73.             string(value_type);
  74.             string(const_reference);                  //assign constructor(string)
  75.             
  76.             string&    operator= (const_reference);         //operator=
  77.             string     operator+ (const_reference) const;   //operator+
  78.             string&    operator+=(const_reference);         //operator+=
  79.             
  80.             //bool operators
  81.             bool       operator==(const_reference) const;    //operator==
  82.             bool       operator==(const_pointer) const;
  83.             bool       operator!=(const_reference) const;    //operator!=
  84.             bool       operator!=(const_pointer) const;
  85.             bool       operator< (const_reference) const;    //operator<
  86.             bool       operator< (const_pointer) const;
  87.             bool       operator> (const_reference) const;    //operator>
  88.             bool       operator> (const_pointer) const;
  89.             bool       operator<=(const_reference) const;    //operator<=
  90.             bool       operator<=(const_pointer) const;
  91.             bool       operator>=(const_reference) const;    //operator>=
  92.             bool       operator>=(const_pointer) const;
  93.             
  94.             value_type&      operator[](const size_type) const;  //operator[]
  95.             value_type&      at(const size_type n) const;
  96.             
  97.             iterator   begin() { return m_data; }
  98.             iterator   end()   { return m_data + _len; }

  99.                 void * operator new (size_type size) { return _str_alloc.allocate(); }
  100.                 void   operator delete (void * mem) { if (mem) _str_alloc.recycle (mem); }
  101.                 static void release () { _str_alloc.deallocate(); }
  102.             
  103.             size_type  size() const { return _len; }
  104.             size_type  length() const { return _len; }
  105.                 string     substr(size_type pos, size_type len) const;
  106.             string&    erase(size_type pos, size_type len);
  107.             void       swap(string& str);
  108.             void       clear();
  109.             bool       empty()  { return !_len; }
  110.             const_pointer c_str() const { return m_data; }
  111.             ~string(void);
  112.         private:
  113.                 static str_allocator _str_alloc;
  114.             value_type *m_data;
  115.             size_type  _len;
  116.             mutable bool local;
  117.         };

  118.         string::str_allocator string::_str_alloc;
  119.         
  120.         inline string::string(const_pointer str)
  121.         {
  122.                 _len   = strlen(str);
  123.         m_data = new value_type[_len+1];
  124.         strcpy(m_data, str);
  125.         local  = true;
  126.         }
  127.         
  128.         inline string::string(value_type ch)
  129.         {
  130.             m_data = new value_type[1];
  131.         m_data[0] = ch;
  132.         _len   = 1;
  133.         local  = true;
  134.         }
  135.         
  136.         inline string::string(const_reference other)
  137.         {
  138.                 local  = false;
  139.             m_data = other.m_data;
  140.             _len   = other._len;
  141.         }
  142.         
  143.         inline string::~string(void)
  144.         {
  145.                 if(local) delete [] m_data;
  146.         }
  147.         
  148.         inline string& string::operator=(const_reference other)
  149.         {
  150.             if (this!=&other)
  151.             {
  152.                 string tmp(other);
  153.                 swap(tmp);
  154.             }
  155.             return *this;
  156.         }
  157.         
  158.         inline string string::operator+(const_reference other)const
  159.         {
  160.             string s;
  161.             s.local = false;
  162.                 s.m_data = new value_type[strlen(m_data)+strlen(other.m_data)+1];
  163.              strcpy(s.m_data,m_data);
  164.             strcat(s.m_data,other.m_data);
  165.             s._len = _len + other._len;
  166.              return s;
  167.         }
  168.         
  169.         inline string& string::operator+=(const_reference other)
  170.         {
  171.             *this = *this + other;
  172.             return *this;
  173.         }
  174.         
  175.         inline bool string::operator==(const_reference s) const
  176.         {
  177.              return s._len == _len
  178.                    && !strcmp(m_data,s.m_data);
  179.         }
  180.         
  181.         inline bool string::operator==(const_pointer s) const
  182.         {
  183.              return strlen(s) == _len
  184.                    && !strcmp(m_data,s);
  185.         }
  186.         
  187.         inline bool string::operator!=(const_reference s) const
  188.         {
  189.              return !(*this == s);
  190.         }
  191.         
  192.         inline bool string::operator!=(const_pointer s) const
  193.         {
  194.              return !(*this == s);
  195.         }
  196.         
  197.         inline bool string::operator< (const_reference s) const
  198.         {
  199.              return strcmp(m_data,s.m_data) < 0;
  200.         }
  201.         
  202.         inline bool string::operator< (const_pointer s) const
  203.         {
  204.              return strcmp(m_data,s) < 0;
  205.         }
  206.         
  207.         inline bool string::operator> (const_reference s) const
  208.         {
  209.              return strcmp(m_data,s.m_data) > 0;
  210.         }
  211.         
  212.         inline bool string::operator> (const_pointer s) const
  213.         {
  214.              return strcmp(m_data,s) > 0;
  215.         }
  216.         
  217.         inline bool string::operator<=(const_reference s) const
  218.         {
  219.              return !(*this > s);
  220.         }
  221.         
  222.         inline bool string::operator<=(const_pointer s) const
  223.         {
  224.              return !(*this > s);
  225.         }
  226.         
  227.         inline bool string::operator>=(const_reference s) const
  228.         {
  229.              return !(*this < s);
  230.         }
  231.         
  232.         inline bool string::operator>=(const_pointer s) const
  233.         {
  234.              return !(*this < s);
  235.         }
  236.         
  237.         inline char& string::operator[](const size_type n) const
  238.         {
  239.              if (n<0 || n>=_len) throw out_of_range();
  240.             return m_data[n];
  241.         }
  242.         
  243.         inline char& string::at(const size_type n) const
  244.         {
  245.              if (n<0 || n>=_len) throw out_of_range();
  246.             return m_data[n];
  247.         }

  248.         inline string string::substr(size_type pos, size_type len) const
  249.         {
  250.                 string s;
  251.                 s.local = false;
  252.                 s.m_data = new value_type[len+1];
  253.                 memcpy(s.m_data, m_data + pos, len);
  254.                 s.m_data[len] = '\0';
  255.                 return s;
  256.         }
  257.         
  258.         inline string& string::erase(size_type pos, size_type len)
  259.         {
  260.                 if (pos >= _len || 0 == len) return *this;
  261.                 const size_type remainder = pos + len;
  262.                 if (remainder >= _len || remainder < pos)
  263.                 {
  264.                 *(m_data + pos) = '\0';
  265.                 _len = pos;
  266.                 return *this;
  267.             }
  268.             size_type left = _len - remainder + 1;
  269.             value_type *d  = m_data + pos;
  270.             value_type *s  = m_data + remainder;
  271.             memmove(d, s, left);
  272.             _len -= len;
  273.             return *this;
  274.         }
  275.         
  276.         inline void string::swap(string& str)
  277.         {
  278.                 string tmp(str);
  279.                
  280.                 str.local  = local;
  281.                 str.m_data = m_data;
  282.                 str._len   = _len;
  283.                
  284.                 local  = tmp.local;
  285.                 m_data = tmp.m_data;
  286.                 _len   = tmp._len;
  287.         }
  288.         
  289.         inline void string::clear()
  290.         {
  291.                 m_data = new value_type[1];
  292.                 strcpy(m_data, "");
  293.                 _len   = 0;
  294.         }

  295.         //String Allocator (Actually a memory pool)
  296.         inline void * string::str_allocator::allocate ()
  297.         {
  298.                 if (_p != 0)
  299.                 {
  300.                         void * mem = _p;
  301.                         _p = _p->_next;
  302.                         return mem;
  303.                 }
  304.                 else
  305.                 {
  306.                         // use global operator new
  307.                         return ::new free [sizeof (char)];
  308.                 }
  309.         }

  310.         inline void string::str_allocator::deallocate ()
  311.         {
  312.                 while (_p != 0)
  313.                 {
  314.                         // it was allocated as an array of char
  315.                         char * mem = reinterpret_cast<char *> (_p);
  316.                         _p = _p->_next;
  317.                         ::delete [] mem;
  318.                 }
  319.         }

  320.         inline void string::str_allocator::recycle(void * mem)
  321.         {
  322.                 free * link = static_cast<free *> (mem);
  323.                 link->_next = _p;
  324.                 _p = link;
  325.         }
  326.         
  327.         istream& operator>>(istream& is, string& str)
  328.         {
  329.             char buffer[1000];
  330.             is >> buffer;
  331.             str = buffer;
  332.              return is;
  333.         }
  334.         
  335.         istream & getline(istream & is, string & str)
  336.         {
  337.             char buffer[1000];
  338.             is.getline(buffer, 1000);
  339.             str = buffer;
  340.             return is;
  341.         }
  342.         
  343.         ostream& operator<<(ostream& os, string& str)
  344.         {
  345.             os << str.c_str();
  346.             return os;
  347.         }
  348.         
  349. } //namespace std

  350. #endif
复制代码
今天很晚了,就不过多讲解了。大家要支持哦~

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2014-3-4 09:01:56 | 显示全部楼层
学习了,支持一下,辛苦了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-5 10:25:37 | 显示全部楼层
希望大家支持我。虽然我水平不怎么高~{:7_168:}
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-9 03:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表