void * operator new(size_t size);
operator new可以显式调用,也可以通过new来调用,new来调用应该申请内存部分交给operator new,
void * operator new(size_t, void *location)
{
return location;
}
void *buffer = // 分配足够的
operator new(50*sizeof(char)); // 内存以容纳50个char
//没有调用构造函数
...
operator delete(buffer); // 释放内存
// 没有调用析构函数
Operator delete用来释放内存,它被这样声明:
void operator delete(void *memoryToBeDeallocated);
// 浅析测试代码
int m_nWritePos = 0;
unsigned char g_arrayBuffer[1000]={0};
void * operator new(size_t size)
{
if(m_nWritePos + size > 1000)
{
return g_arrayBuffer + m_nWritePos;
}
else
{
m_nWritePos += size;
return g_arrayBuffer + m_nWritePos;
}
}
void operator delete(void *pNum)
{
//if(m_nWritePos + size > 1000)
//{
// //return g_arrayBuffer + m_nWritePos;
// m_nWritePos -= (m_nWritePos + size - 1000);
//}
//else
//{
// m_nWritePos -= size;
// //return g_arrayBuffer + m_nWritePos;
//}
m_nWritePos -= 10;
}
void * operator new(size_t size, void *pLocation)
{
return pLocation;
}
//void * operator delete(size_t size, void *pLocation)
//{
// return pLocation;
//}
int main()
{
int *pNum = /*new int*/(int*)operator new(10);// 如果直接new int(10) 则operator new(10)也会得到调用
delete pNum;// 调用析构函数,释放内存空间
int *pNum2 = (int*)operator new(10, pNum);// new(10, pNum) 只是返回对象的指针,所以分配内存的placement new没有得到调用
}
使用实例:
分配和释放内存:
// Node memory management
Node *AllocateNode()
{
#if !USE_FSA_MEMORY
Node *p = new Node;
return p;
#else
// 从内存池中获取一个对象,也可以重载operator new (size_t size)实现内存分配。
Node *address = m_FixedSizeAllocator.alloc();
if( !address )
{
return NULL;
}
m_AllocateNodeCount ++;
// 用placement new简单的返回地址address,主要的是前后的new Node达到调用构造函数目的,实现对象和地址绑定
Node *p = new (address) Node;
return p;
#endif
}
void FreeNode( Node *node )
{
m_AllocateNodeCount --;
#if !USE_FSA_MEMORY
delete node;
#else
// 手动调用析构函数,因为operator delete(size_t size)等形式的只是new出错才调用,否则不能手动调用
node->~Node();
m_FixedSizeAllocator.free( node ); // 回收对象到内存池中
#endif
}
内存池构建:
#include <string.h>
#include <stdio.h>
template <class USER_TYPE> class FixedSizeAllocator
{
public:
// Constants
enum
{
FSA_DEFAULT_SIZE = 100
};
// This class enables us to transparently manage the extra data
// needed to enable the user class to form part of the double-linked
// list class
struct FSA_ELEMENT
{
USER_TYPE UserType;
FSA_ELEMENT *pPrev;
FSA_ELEMENT *pNext;
};
public: // methods
FixedSizeAllocator( unsigned int MaxElements = FSA_DEFAULT_SIZE ) :
m_pFirstUsed( NULL ),
m_MaxElements( MaxElements )
{
// Allocate enough memory for the maximum number of elements
char *pMem = new char[ m_MaxElements * sizeof(FSA_ELEMENT) ];
m_pMemory = (FSA_ELEMENT *) pMem;
// Set the free list first pointer
m_pFirstFree = m_pMemory;
// Clear the memory
memset( m_pMemory, 0, sizeof( FSA_ELEMENT ) * m_MaxElements );
// Point at first element
FSA_ELEMENT *pElement = m_pFirstFree;
// Set the double linked free list
for( unsigned int i=0; i<m_MaxElements; i++ )
{
pElement->pPrev = pElement-1;
pElement->pNext = pElement+1;
pElement++;
}
// first element should have a null prev
m_pFirstFree->pPrev = NULL;
// last element should have a null next
(pElement-1)->pNext = NULL;
}
~FixedSizeAllocator()
{
// Free up the memory
delete [] (char *) m_pMemory;
}
// Allocate a new USER_TYPE and return a pointer to it
USER_TYPE *alloc()
{
FSA_ELEMENT *pNewNode = NULL;
if( !m_pFirstFree )
{
return NULL;
}
else
{
pNewNode = m_pFirstFree;
m_pFirstFree = pNewNode->pNext;
// if the new node points to another free node then
// change that nodes prev free pointer...
if( pNewNode->pNext )
{
pNewNode->pNext->pPrev = NULL;
}
// node is now on the used list
pNewNode->pPrev = NULL; // the allocated node is always first in the list
if( m_pFirstUsed == NULL )
{
pNewNode->pNext = NULL; // no other nodes
}
else
{
m_pFirstUsed->pPrev = pNewNode; // insert this at the head of the used list
pNewNode->pNext = m_pFirstUsed;
}
m_pFirstUsed = pNewNode;
}
return reinterpret_cast<USER_TYPE*>(pNewNode);
}
// Free the given user type
// For efficiency I don't check whether the user_data is a valid
// pointer that was allocated. I may add some debug only checking
// (To add the debug check you'd need to make sure the pointer is in
// the m_pMemory area and is pointing at the start of a node)
void free( USER_TYPE *user_data )
{
FSA_ELEMENT *pNode = reinterpret_cast<FSA_ELEMENT*>(user_data);
// manage used list, remove this node from it
if( pNode->pPrev )
{
pNode->pPrev->pNext = pNode->pNext;
}
else
{
// this handles the case that we delete the first node in the used list
m_pFirstUsed = pNode->pNext;
}
if( pNode->pNext )
{
pNode->pNext->pPrev = pNode->pPrev;
}
// add to free list
if( m_pFirstFree == NULL )
{
// free list was empty
m_pFirstFree = pNode;
pNode->pPrev = NULL;
pNode->pNext = NULL;
}
else
{
// Add this node at the start of the free list
m_pFirstFree->pPrev = pNode;
pNode->pNext = m_pFirstFree;
m_pFirstFree = pNode;
}
}
// For debugging this displays both lists (using the prev/next list pointers)
void Debug()
{
printf( "free list " );
FSA_ELEMENT *p = m_pFirstFree;
while( p )
{
printf( "%x!%x ", p->pPrev, p->pNext );
p = p->pNext;
}
printf( "\n" );
printf( "used list " );
p = m_pFirstUsed;
while( p )
{
printf( "%x!%x ", p->pPrev, p->pNext );
p = p->pNext;
}
printf( "\n" );
}
// Iterators
USER_TYPE *GetFirst()
{
return reinterpret_cast<USER_TYPE *>(m_pFirstUsed);
}
USER_TYPE *GetNext( USER_TYPE *node )
{
return reinterpret_cast<USER_TYPE *>
(
(reinterpret_cast<FSA_ELEMENT *>(node))->pNext
);
}
public: // data
private: // methods
private: // data
FSA_ELEMENT *m_pFirstFree;
FSA_ELEMENT *m_pFirstUsed;
unsigned int m_MaxElements;
FSA_ELEMENT *m_pMemory;
};