10分钟教你用内存池管理C++语言对象
小标 2018-06-25 来源 : 阅读 807 评论 0

摘要:在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+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程