摘要:在C++语言中,当一个系统 ,有一些对象需要频繁的申请和释放时,为了提高性能我们通常用内存池来管理这部分对象,这里给一个内存池的实现,我们用双向链表和数组实现内存池来管理c++对象。希望对大家学习C++语言有所帮助。
在C++语言中,当一个系统 ,有一些对象需要频繁的申请和释放时,为了提高性能我们通常用内存池来管理这部分对象,这里给一个内存池的实现,我们用双向链表和数组实现内存池来管理c++对象。希望对大家学习C++语言有所帮助。
内存池类
[cpp] view plain copy 1. // 2. // mempool.h 3. // Created by DGuco on 17/7/29. 4. // Copyright © 2017年 DGuco. All rights reserved. 5. // 结合数组和双向链表实现对象内存池(注:使用该内存的类必须有无参的构造函数) 6. // 7. 8. #ifndef SERVER_MEMPOOL_H 9. #define SERVER_MEMPOOL_H 10. 11. #include <clocale> 12. template<class type=""> 13. class CMemoryPool 14. { 15. public: 16. CMemoryPool(void) : m_pElementsSetList(NULL),m_pUnusedElementsList(NULL) 17. { 18. 19. } 20. ~CMemoryPool(void) 21. { 22. if (GetPoolSize() > 0 || IsCreated()){ 23. //注意这里一般手动调用Destroy,在析构函数中调用是为了防止我们忘记手动调用` 24. Destroy(); 25. } 26. } 27. 28. //简直拷贝和赋值 29. CMemoryPool(const CMemoryPool& other) = delete ; 30. CMemoryPool&operator=(CMemoryPool& other) = delete; 31. private: 32. //节点数据结构 33. struct TagElement 34. { 35. Type Element; 36. TagElement* pNext; 37. TagElement* pBefore; 38. }; 39. 40. //对象数组,注意这里的next的用途,当内存池的容量不够使,会另外开辟同等大小的空间来存储对象, 41. //新数组的next会指向旧的数组,其实是一个链表,每个节点是一个数组 42. struct TagElementsSet 43. { 44. //对象数组 45. TagElement* aElementsSet; 46. TagElementsSet* pNext; 47. }; 48. 49. //对象池数组 50. TagElementsSet* m_pElementsSetList; 51. //使用数量 52. int m_nNumOfAlloc; 53. //当前可用的节点 54. TagElement* m_pUnusedElementsList; 55. //一个数组的最大对象数量也是内存池的初始大小 56. int m_nNumOfElements; 57. //数组数量 58. int m_nNumOfElementsSet; 59. 60. public: 61. //开辟指定数量的内存池 62. bool Create( uint nNumOfElements ) 63. { 64. m_nNumOfElements = nNumOfElements; 65. m_nNumOfElementsSet = 1; 66. 67. m_pElementsSetList = new TagElementsSet; 68. m_pElementsSetList->pNext = NULL; 69. //开辟数组 70. m_pElementsSetList->aElementsSet = new TagElement[m_nNumOfElements]; 71. 72. //初始化链表结构 73. for( int i = 0; i < m_nNumOfElements; i++ ) 74. { 75. if( i > 0 ) 76. { 77. m_pElementsSetList->aElementsSet[i].pBefore = &m_pElementsSetList->aElementsSet[i-1]; 78. m_pElementsSetList->aElementsSet[i-1].pNext = &m_pElementsSetList->aElementsSet[i]; 79. } 80. } 81. m_pElementsSetList->aElementsSet[0].pBefore = NULL; 82. m_pElementsSetList->aElementsSet[m_nNumOfElements-1].pNext = NULL; 83. 84. //当前可用的节点信息 85. m_pUnusedElementsList = m_pElementsSetList->aElementsSet; 86. m_nNumOfAlloc = 0; 87. return true; 88. } 89. 90. //回收内存池 91. void Destroy() 92. { 93. while( m_pElementsSetList ) 94. { 95. if( m_pElementsSetList->aElementsSet ) 96. { 97. delete[] m_pElementsSetList->aElementsSet; 98. m_pElementsSetList->aElementsSet = NULL; 99. } 100. TagElementsSet* pFirst = m_pElementsSetList; 101. m_pElementsSetList = m_pElementsSetList->pNext; 102. 103. delete pFirst; 104. } 105. m_nNumOfAlloc = 0; 106. m_nNumOfAlloc = 0; 107. m_nNumOfElementsSet = 0; 108. } 109. 110. Type* Alloc() 111. { 112. //如果当前的链表使用完,开辟新的一条同等大小的链表 113. if( m_pUnusedElementsList == NULL ) 114. { 115. TagElementsSet* pSet = new TagElementsSet; 116. //把next之乡旧的数组 117. pSet->pNext = m_pElementsSetList; 118. pSet->aElementsSet = new TagElement[m_nNumOfElements]; 119. 120. //初始化链表信息 121. for( int i = 0; i < m_nNumOfElements; i++ ) 122. { 123. if( i > 0 ) 124. { 125. pSet->aElementsSet[i].pBefore = &pSet->aElementsSet[i-1]; 126. pSet->aElementsSet[i-1].pNext = &pSet->aElementsSet[i]; 127. } 128. } 129. pSet->aElementsSet[0].pBefore = NULL; 130. pSet->aElementsSet[m_nNumOfElements-1].pNext = NULL; 131. 132. //把当前可用节点指向新数组的第一个元素 133. m_pUnusedElementsList = pSet->aElementsSet; 134. 135. m_pElementsSetList = pSet; 136. m_nNumOfElementsSet++; 137. } 138. 139. TagElement* pTagElement; 140. pTagElement = m_pUnusedElementsList; 141. m_pUnusedElementsList = m_pUnusedElementsList->pNext; 142. if( m_pUnusedElementsList ) 143. { 144. m_pUnusedElementsList->pBefore = NULL; 145. 146. } 147. 148. m_nNumOfAlloc++; 149. return &(pTagElement->Element); 150. } 151. 152. //回收一个对象 153. void Free( Type* pElement ) 154. { 155. TagElement* pTagElement = (TagElement*)pElement; 156. pTagElement->pNext = m_pUnusedElementsList; 157. pTagElement->pBefore = NULL; 158. if( m_pUnusedElementsList ) 159. m_pUnusedElementsList->pBefore = pTagElement; 160. m_pUnusedElementsList = pTagElement; 161. m_nNumOfAlloc--; 162. } 163. 164. int GetAllocatedSize() 165. { 166. return m_nNumOfAlloc; 167. } 168. 169. int GetPoolSize() 170. { 171. return m_nNumOfElements * m_nNumOfElementsSet; 172. } 173. 174. bool IsCreated() 175. { 176. return m_pElementsSetList != NULL; 177. } 178. 179. };// class CMemoryPool 180. 181. #endif //SERVER_MEMPOOL_H 182. </class></clocale>
内存池安全操作接口
[cpp] view plain copy 1. // 2. // 3. // Created by DGuco on 17/7/29. 4. // Copyright © 2017年 DGuco. All rights reserved. 5. // 内存池安全操作接口,线程安全 6. // 7. 8. #ifndef SERVER_MEMPOOLSAFTY_H 9. #define SERVER_MEMPOOLSAFTY_H 10. 11. #include <mutex> 12. #include "mempool.h" 13. 14. /* 注意:创建和回收整个内存池两个操作不是线程安全的, 15. * 这里没有锁保护是因为因为这两个操作一般在主线程中, 16. * 使用的时候才会出现多线程同时操作 17. */ 18. template<class type=""> 19. class CMemoryPoolSafty : public CMemoryPool<type> 20. { 21. private: 22. std::mutex m_utex; 23. 24. public: 25. //创建sizeof(Type) * nNumOfElements大小的空间 26. bool Create(uint nNumOfElements) 27. { 28. return CMemoryPool<type>::Create(nNumOfElements); 29. } 30. 31. //释放内存池空间 32. void Destroy() 33. { 34. CMemoryPool<type>::Destroy(); 35. } 36. 37. //从内存池中获取一个对象空间 38. Type* Alloc() 39. { 40. std::lock_guard<std::mutex> guard(m_utex); 41. Type* pType; 42. pType = CMemoryPool<type>::Alloc(); 43. return pType; 44. } 45. 46. //内存池回收一个对象空间 47. void Free( Type* pElement ) 48. { 49. std::lock_guard<std::mutex> guard(m_utex); 50. CMemoryPool<type>::Free(pElement); 51. } 52. }; 53. #endif //SERVER_MEMPOOLSAFTY_H 54. </type></std::mutex></type></std::mutex></type></type></type></class></mutex>
使用例子:
[cpp] view plain copy 1. // 2. // 3. // Created by DGuco on 17/7/29. 4. // Copyright © 2017年 DGuco. All rights reserved. 5. // 内存池安全操作接口,线程安全 6. // 7. 8. #include <vector> 9. #include <iostream> 10. #include <string> 11. #include "memsafety.h" 12. 13. using namespace std; 14. 15. class Demo 16. { 17. public: 18. Demo() 19. { 20. name = ""; 21. age = 0; 22. } 23. 24. void init(string _name,int _age) 25. { 26. name = _name; 27. age = _age; 28. } 29. 30. string GetName() {return name;} 31. int GetAge() {return age;} 32. private: 33. string name; 34. int age; 35. }; 36. 37. int main() 38. { 39. CMemoryPool<demo> memPool; 40. //初始化内存池大小 41. memPool.Create(5); 42. std::vector<demo*> demoArray; 43. 44. for (int i = 0; i< 10;i++) { 45. Demo *demo = memPool.Alloc(); 46. demo->init(to_string(i), i); 47. demoArray.push_back(demo); 48. } 49. 50. for (int i = 0; i< 10;i++) { 51. std::cout<< "name:" << demoArray[i]->GetName() << " age:" << demoArray[i]->GetAge() << std::endl; 52. memPool.Free(demoArray[i]); 53. } 54. 55. memPool.Destroy(); 56. std::cout << "Hello word" << std::endl; 57. }</demo*></demo></string></iostream></vector>
本文由职坐标整理并发布,了解更多内容,请关注职坐标编程语言C/C+频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号