struct FreeBlock {
FreeBlock* pNext;
FreeBlock( FreeBlock* pNextFree = 0 ) :
pNext( pNextFree ) {}
};
T* BlockAlloc<T>::alloc() {
if ( m_freeList ) {
FreeBlock* pBlock = m_freeList;
m_freeList = pBlock->pNext;
pBlock->~FreeBlock(); // Destruct FreeBlock
// Use placement new to construct T
return new ( pBlock ) T();
} else {
// Get raw memory and set up free list
...
}
}
void BlockAlloc<T>::free( T* pt ) {
if ( pt ) {
pt->~T(); // Destruct T
m_freeList = new ( pt ) FreeBlock( m_freeList );
}
}
This is a very simple example, used only for illustration. The use of placement
new
allows us to construct only the T
objects that are currently in use, but allows us to allocate enough memory for a large number of them.Calling the
FreeBlock
destructor is seemingly unnecessary since FreeBlock
only has an implicit destructor. However, it's maintainable to do so. What if someone later adds a destructor to FreeBlock
to, say, decrement a count of FreeBlock
objects?This is a simple example; placement
new
is great for many things: containers, singleton objects that you don't want on the heap (but want to control when they are constructed), memory management structures, game resource management and so on.
No comments:
Post a Comment