标签:operator char 之间 使用 ++ 带来 示例 out debug
一、内存池的概念和实现原理
内存池要解决的问题:
(1)减少malloc的次数,意味着减少对内存的浪费(主要问题)
(2)减少malloc的次数,会有一些速度和效率上的提升,但是提升不明显(顺带)
实现原理:
(1)用malloc申请一大块内存,当要分配的时候,从这一大块内存中一点一点分配,
当这一大块内存分配的差不多的时候,在申请一大块内存,然后再一点一点分配。
(因为每次malloc的时候,还会分配一些debug,尾信息,等一些附加信息的内存
所以malloc次数少了,就可以避免每次malloc带来的一些附加分配的内存空间)
二、代码示例
class A { public: static int m_iCount; // 每new一次记录一次 static int m_iMallocCount; // 每malloc一次记录一次 // malloc 一块大的内存 可以new多次 static void* operator new(size_t size); // size分配的内存大小 static void operator delete(void* pa);private: A * pNext; // 指向下一个 static A* m_FreePos; // 总是指向一块可以分配出去的内存的首地址 static int m_sTrunkCount; // 一次分配多少倍的该类内存 }; int A::m_iCount = 0; int A::m_iMallocCount = 0; A* A::m_FreePos = nullptr; int A::m_sTrunkCount = 50; // 一次分配5倍的该类内存作为内存池大小,一般分配几十,根据具体情况而定 void* A::operator new(size_t size) // 这个size是系统根据类的大小指定的 { //A* pa = (A*)malloc(size); //return pa; A* pTemp; if (m_FreePos == nullptr) { // 为空,我需要申请一大块内存 size_t realsize = m_sTrunkCount * size; m_FreePos = reinterpret_cast<A*>(new char[realsize]); // reinterpret_cast 无条件转 // 此处的new是传统的new(不是我们自己定义的new)该出调用的是底层的malloc pTemp = m_FreePos; // 把分配的这一大块内存(5小块)彼此之间链接起来,供后续使用
// 用链表的方式来管理内存池的内存
for (; pTemp != &m_FreePos[m_sTrunkCount - 1]; ++pTemp) { pTemp->pNext = pTemp + 1; } pTemp->pNext = nullptr; // 最后一个 ++m_iMallocCount; } pTemp = m_FreePos; m_FreePos = m_FreePos->pNext; ++m_iCount; return pTemp; // new第二块新内存的时候,第一块内存的最后一个元素,还是指向第二块内存的起始地址m_FreePos // 这个关系式在new第一块内存的时候建立的链接关系 } void A::operator delete(void* pa) { //free(pa); (static_cast<A*>(pa))->pNext = m_FreePos; // 将需要释放的这块内存作为下一个将要被释放的内存,则m_FreePos变成了下两个将被释放的内存 // 因为释放的顺序是随机的 m_FreePos = static_cast<A*>(pa); // 回收内存的时候,是回收在内存池中,而不是回收到系统中 // 回收到内存池中,被内存池控制,所以不会有内存泄漏 }void fun(){ clock_t start, end; start = clock(); for (int i = 0; i < 5000000; ++i) { A* pa = new A(); } end = clock(); cout << "new 次数:" << A::m_iCount << " Malloc 次数:" << A::m_iMallocCount << " 耗时:" << end - start << endl; }
标签:operator char 之间 使用 ++ 带来 示例 out debug
原文地址:https://www.cnblogs.com/zhiminzeng/p/13222225.html