C++实现内存池

释放双眼,带上耳机,听听看~!

人家对内存块的管理是用vector,动态的插入与删除,来做内存的分配与回收,基于人家的代码,做的一些改动,用Map进行管理,用标志来区分该内存块是否已分配,回收时,内存里面的内容也得重置掉,以免影响下一次的调用。
代码如下


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
1
2#ifndef _MEM_POOL_H
3#define _MEM_POOL_H
4
5#include <vector>
6#include <iostream>
7#include <map>
8#include "string.h"
9
10
11using namespace std;
12
13/*
14在内存池中分配固定大小的内存块
15
16该类的目的是加速内存分配速度,并且减少因重复分配相同
17内存时产生的内存碎片,比如在服务器应用程序中。
18*/
19
20struct sBlock
21{
22    short   isHasUse; // 是否使用过
23    int     iIndx;    // 编号
24    char*   pBlock;   // 内存块所指向的地址
25};
26
27class CMemPool
28{
29public:
30
31    //创建大小为blockSize的内存块,内存池数目为预分配的数目preAlloc
32    CMemPool(std::size_t blockSize, int preAlloc = 0);
33
34    ~CMemPool();
35
36    //获取一个内存块。如果内存池中没有足够的内存块,则会自动分配新的内存块
37    //如果分配的内存块数目达到了最大值,则会返回一个异常
38    void* Get();
39
40    //释放当前内存块,将其插入内存池
41    void Release(void* ptr);
42
43    //返回内存块大小
44    std::size_t BlockSize() const;
45
46    //返回内存池中内存块数目
47    int Allocated() const;
48
49    //返回内存池中可用的内存块数目
50    int Available() const;
51
52    //得到内存块的数量
53    int GetBlockNum() const;
54
55private:
56    CMemPool();
57    CMemPool(const CMemPool&);
58    CMemPool& operator = (const CMemPool&);
59
60    enum
61    {
62        BLOCK_RESERVE = 32
63    };
64
65    typedef std::vector<char*> BlockVec;
66
67    std::size_t m_blockSize;
68    int         m_maxAlloc;
69    int         m_allocated;
70    BlockVec    m_blocks;
71
72    typedef map<int, sBlock> BlockMap;
73    BlockMap    m_blocks_map;
74
75};
76
77inline std::size_t CMemPool::BlockSize() const
78{
79    return m_blockSize;
80}
81
82
83// 得到已经分配出去的有多少
84inline int CMemPool::Allocated() const
85{
86    int iTotalUseNum = 0;
87    for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
88    {
89        if (it->second.isHasUse == 1)
90        {
91            iTotalUseNum += 1;
92        }
93    }
94    return iTotalUseNum;
95}
96
97inline int CMemPool::Available() const
98{
99    int iAvailableNum = 0;
100    for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
101    {
102        if (it->second.isHasUse == 0)
103        {
104            iAvailableNum += 1;
105        }
106    }
107    return iAvailableNum;
108}
109
110inline int CMemPool::GetBlockNum() const
111{
112    return m_blocks_map.size();
113}
114
115CMemPool::CMemPool(std::size_t blockSize, int preAlloc) :
116m_blockSize(blockSize),
117m_allocated(preAlloc)
118{
119    m_blocks_map.clear();
120    for (int i = 0; i < preAlloc; ++i)
121    {
122        sBlock nBlock;
123        nBlock.isHasUse = 0;
124        nBlock.iIndx = i;
125        nBlock.pBlock = new char[m_blockSize];
126        m_blocks_map[i] = nBlock;
127    }
128
129}
130
131CMemPool::~CMemPool()
132{
133    for (BlockMap::iterator it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
134    {
135
136        cout << " delete the block indx = " << it->second.iIndx << "  " << endl;
137        delete[] it->second.pBlock; // 删除内存对应的内存空间
138    }
139    m_blocks_map.clear();
140}
141
142
143void* CMemPool::Get()
144{
145     // 分配内存地址
146    for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
147    {
148        if (it->second.isHasUse == 0)
149        {
150            it->second.isHasUse = 1; // 表示该内存块已经被分配出去了
151            cout << " this block indx = " << it->second.iIndx << "  has be used " << endl;
152            return it->second.pBlock;
153        }
154    }
155
156    // 如果内存map 都被用完啦,那么则得添加新的内存块到map中
157    auto iter = m_blocks_map.end();
158    iter--; // 得往后减一个,才能取到最后一个元素
159
160    int maxIndx = iter->second.iIndx;
161
162    int curIndx = maxIndx + 1;
163    sBlock nBlock;
164    nBlock.iIndx = curIndx;
165    nBlock.isHasUse = 0;
166    nBlock.pBlock = new char[m_blockSize];
167    m_blocks_map[curIndx] = nBlock;
168
169    // 将新添加的分配出来用
170    m_blocks_map[curIndx].isHasUse = 1;
171    cout << " this block indx = " << m_blocks_map[curIndx].iIndx << " create and  has be used " << endl;
172    return m_blocks_map[curIndx].pBlock;
173
174}
175
176
177void CMemPool::Release(void* ptr)
178{
179    for (auto it = m_blocks_map.begin(); it != m_blocks_map.end(); ++it)
180    {
181        char * pTmp = reinterpret_cast<char*>(ptr);
182        if (it->second.pBlock == pTmp)
183        {
184            cout << " the block indx = " << it->second.iIndx << "   has be Released " << endl;
185            it->second.isHasUse = 0;
186            memset(pTmp, 0, m_blockSize);
187        }
188    }
189}
190
191
192#endif
193

测试代码


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
1#include "MemPool.h"
2
3#define DATA_BLOCK_LEN 50
4
5struct  sTest
6{
7    int m_id;
8    int m_num;
9};
10
11struct  sTest2
12{
13    int m_id;
14    int m_num;
15    char m_str[10];
16};
17
18int main()
19{
20    CMemPool myPool1(DATA_BLOCK_LEN, 20);
21
22    cout << "myPool1 block size = " << myPool1.BlockSize() << endl;
23    cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
24    cout << "myPool1 available block num = " << myPool1.Available() << endl;
25    cout << "myPool1 total block num = " << myPool1.GetBlockNum() << endl <<endl;
26
27    // 分配一个内存块
28    struct sTest* pTest;
29    pTest = (struct sTest*)(myPool1.Get());
30
31    pTest->m_id = 25;
32    pTest->m_num = 10000;
33    cout << pTest->m_id <<"  " <<pTest->m_num << endl;
34
35    struct sTest* pTest2;
36    pTest2 = (struct sTest*)(myPool1.Get());
37
38    pTest2->m_id = 123;
39    pTest2->m_num = 13445;
40    cout << pTest2->m_id << "  " << pTest2->m_num << endl << endl;
41
42
43    cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
44    cout << "myPool1 available block num = " << myPool1.Available() << endl << endl;
45
46    // 回收该内存块
47    myPool1.Release(pTest);
48    pTest = NULL;
49
50    cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
51    cout << "myPool1 available block num = " << myPool1.Available() << endl << endl;
52
53    //pTest = (struct sTest*)(myPool1.Get());
54    //cout << pTest->m_id << endl;
55    //cout << pTest->m_num << endl;
56    struct sTest2* pTtmp;
57    pTtmp = (struct sTest2*)(myPool1.Get());
58    pTtmp->m_id = 1234;
59    char * cTmp= "skskdlsl";
60    memcpy(pTtmp->m_str, cTmp, strlen(cTmp));
61    cout << pTtmp->m_str << endl;
62
63    cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
64    cout << "myPool1 available block num = " << myPool1.Available() << endl << endl;
65
66    myPool1.Release(pTtmp);
67
68    for (int i = 0; i < 30; ++i)
69    {
70        struct sTest* pTest3;
71        pTest3 = (struct sTest*)(myPool1.Get());
72
73        pTest3->m_id = 123;
74        pTest3->m_num = 13445;
75        cout << pTest3->m_id << "  " << pTest3->m_num << endl << endl;
76        cout << "myPool1 allocated block num = " << myPool1.Allocated() << endl;
77        cout << "myPool1 available block num = " << myPool1.Available() << endl;
78        cout << "myPool1 total block num = " << myPool1.GetBlockNum() << endl << endl;
79    }
80
81    int iWait;
82    cin >> iWait;
83
84    return 0;
85}
86

给TA打赏
共{{data.count}}人
人已打赏
安全技术

C++中引用和指针的区别

2022-1-11 12:36:11

安全运维

深度学习 -- > NLP-- > BERT

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索