在c/c++中記憶體的管理是非常頭痛的事情,這裡作者不再多解釋,請參考這篇文章:作者也是參考這篇文章進行對記憶體池的改進和進化。
1、封裝乙個類用於管理記憶體池的使用如下,很容易看得懂,其實就是向記憶體池申請size個空間並進行構造,返回是首個元素的位址。釋放也是一樣,不過釋放多個的時候需要確保這多個元素的記憶體是連續的。
#pragma once
#include template>
class allocatemanager
//allocator申請空間
t * allocatejj(size_t size = 1)
//釋放並**空間
void destroy(t * node, size_t size = 1) }
//獲得當前記憶體池的大小
const size_t getmenorysize()
//獲得當前記憶體池的塊數
const size_t getblocksize()
};
rebind的設計跟c++stl裡的設計是同樣套路,stl設計**如下:
templateclass basic_string
: public _string_val<_elem _ax>
; ...
2、記憶體池設計**,下面會乙個乙個方法拋開說明
#pragma once
#include templateclass memorypool
; memorypool()
~memorypool() }
//申請空間
t * allocateone()
//申請一塊記憶體
if (m_currentslot >= m_laterslot)
return reinterpret_cast(m_currentslot++);
} /*動態分配空間,注意:分配超過2個空間會在塊裡面建立占用4位元組的空間存放陣列的指標,
這個空間不會被**,所以動態分配最好分配大空間才使用動態
*/ t * allocate(size_t size = 1)
; //申請乙個空間
if (size == 1)
return allocateone();
slot_pointer presult = nullptr;
/*先計算最後申請的塊空間夠不夠,不適用**的空間,因為**空間不是連續*/
int canusesize = reinterpret_cast(m_laterslot) + sizeof(slot_) - 1 - reinterpret_cast(m_currentslot);
/*空間不夠動態分配塊大小,不把上一塊剩餘的空間使用是因為空間是需要連續,
所以上一塊會繼續往前推供下次使用*/
m_blocksize++;
if (!m_headslot)//目前沒有一塊記憶體情況
else
return reinterpret_cast(presult);
} //使用空間
void construct(t * p, size_t size = 1)
//析構乙個物件
void destroy(t * p)
//**乙個空間
void deallocate(t * p, size_t count = 1)
; reinterpret_cast(p)->next = m_freeheadslot;
m_freeheadslot = reinterpret_cast(p);
} const size_t getmenorysize()
const size_t getblocksize()
private:
union slot_
; typedef slot_* slot_pointer;
typedef char* char_pointer;
slot_pointer m_freeheadslot;//空閒的空間頭部位置
slot_pointer m_headslot;//指向的頭位置
slot_pointer m_currentslot;//當前所指向的位置
slot_pointer m_laterslot;//指向最後乙個元素的開始位置
size_t m_menorysize;
size_t m_blocksize;
// 同步
std::mutex m_lock;
static_assert(blocksize > 0, "blocksize can not zero");
};
3、申請乙個空間,當**的記憶體沒有或記憶體塊空間不夠時,新開闢一塊記憶體,並將新記憶體放在表頭,返回新記憶體的頭位址,如果記憶體塊還有空間,那麼返回首個空餘的空間
//申請空間
t * allocateone()
//申請一塊記憶體
if (m_currentslot >= m_laterslot)
return reinterpret_cast(m_currentslot++);
}
4、當分配超過2個元素空間時,先判斷空閒塊的空間夠不夠分配,夠分配,不夠新開闢乙個大小跟申請元素個數一樣的記憶體塊,並將該塊記憶體向表頭置後,返回該快首位址。注意,由於分配多個元素的空間也就是分配乙個陣列,這個時候在下一步呼叫建構函式時會構造陣列物件,陣列物件會多乙個指標空間指向該陣列,所以申請n+1個元素時加上乙個指標的空間,否則會洩漏。
這個指標的空間是沒有用的,釋放和**空間是不會**這個指標,這樣它就會占用了記憶體塊乙個指標空間,就相當於磁碟分割槽有未分配的記憶體一樣,分配多個元素空間時這個是無法避免的。
/*動態分配空間,注意:分配超過2個空間會在塊裡面建立占用4位元組的空間存放陣列的指標,
這個空間不會被**,所以動態分配最好分配大空間才使用動態
*/ t * allocate(size_t size = 1)
; //申請乙個空間
if (size == 1)
return allocateone();
slot_pointer presult = nullptr;
/*先計算最後申請的塊空間夠不夠,不適用**的空間,因為**空間不是連續*/
int canusesize = reinterpret_cast(m_laterslot) + sizeof(slot_) - 1 - reinterpret_cast(m_currentslot);
/*空間不夠動態分配塊大小,不把上一塊剩餘的空間使用是因為空間是需要連續,
所以上一塊會繼續往前推供下次使用*/
m_blocksize++;
if (!m_headslot)//目前沒有一塊記憶體情況
else
return reinterpret_cast(presult);
}
其他小的方法就不介紹了,**也有注釋很容易看得懂。
5、效能測試
動態分配時,num1表示分配塊數,num2表示分配的每塊大小。
逐步申請和釋放一千萬個空間(元素為單位),速度如下,c++是最慢的,memorypool快樂接近20倍,memorypool動態分配會更快樂些(面對疾風吧)。
測試**:
#include #include #include #include #include #include"memorypool.h"
#include"allocatemanager.h"
using namespace std;
//動態分配時,num1表示塊數,num2表示每塊大小
#define num1 1000
#define num2 10000
class test
};void testbycjj()
} //根據物件從記憶體池釋放並**該空間
for (int i = 0; i < num1; i++) }
std::cout << "c++ time: ";
std::cout << (((double)clock() - start) / clocks_per_sec) << endl;
}void testbyone()
} for (int i = 0; i < num1; i++) }
std::cout << "memorypool one time: ";
std::cout << (((double)clock() - start) / clocks_per_sec);
std::cout << " 記憶體塊數量:" << memorypool.getblocksize();
std::cout << " 記憶體消耗(byte):" << memorypool.getmenorysize() << std::endl;
}void testbyblock()
} for (int i = 0; i < num1; i++) }
std::cout << "memorypool block time: ";
std::cout << (((double)clock() - start) / clocks_per_sec);
std::cout << " 記憶體塊數量:" << memorypool.getblocksize();
std::cout << " 記憶體消耗(byte):" << memorypool.getmenorysize() << std::endl;
}int main()
工程檔案鏈 記憶體動態分配
陣列的元素儲存於記憶體中連續的位置上。當乙個陣列被宣告時,它所需要的內存在編譯時就被分配。但是,你也可以使用動態記憶體分配在執行時為它分配記憶體。malloc所分配的是一塊連續的記憶體。例如,如果請求它分配100個位元組的記憶體,那麼它實際分配的記憶體就是100個連續的位元組,並不會分開位於兩塊或多...
動態分配記憶體
動態記憶體分配即分配記憶體大小在執行時才確定,一般在堆中分配。c語言動態記憶體分配相關的函式。include void malloc size t size malloc的使用比較直接,乙個成功的malloc呼叫返回分配的size大小的記憶體的指標。失敗時返回null並將錯誤 置為enomem。教材...
動態分配記憶體
動態分配記憶體 動態分配記憶體也可以分配儲存區,這種方式可以在程式執行的時候臨時決定分配的儲存區大小 為了管理動態分配的記憶體,就需要使用一組標準函式 為了使用這些標準函式,需要包含stdlib.h標頭檔案 malloc 函式可以動態分配一組連續的位元組 這個函式需要乙個整數型別引數表示分配的位元組...