我正在尝试升级我们的池化固定块内存分配器以利用C ++ 11类型的特性。
目前,可以通过以传统方式覆盖the global new operator来强制将任何对象的任何分配分配到正确的池,例如
void* operator new (std::size_t size)
{ // if-cascade just for simplest possible example
if ( size <= 64 ) { return g_BlockPool64.Allocate(); }
else if ( size <= 256 ) { return g_BlockPool256.Allocate(); }
// etc .. else assume arguendo that we know the following will work properly
else return malloc(size);
}
在许多情况下,如果可以根据类型特征(例如is_trivially_destructible
)将对象分派到不同的池,我们可以进一步提高性能。 是否可以制作一个知道分配类型的模板化全局新运算符,而不仅仅是请求的大小?等同于
template<class T>
void *operator new( size_t size)
{
if ( size < 64 )
{ return std::is_trivially_destructible<T>::value ?
g_BlockPool64_A.Allocate() :
g_BlockPool64_B.Allocate(); } // etc
}
在每个类中覆盖成员new运算符在此处不起作用;我们真的需要它自动适用于任何地方的任何分配。 Placement new也不起作用:要求每个alloc看起来像
Foo *p = new (mempool<Foo>) Foo();
过于繁琐,人们会忘记使用它。
答案 0 :(得分:3)
简短的回答是否定的。分配/释放功能具有以下签名:
void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
与这些签名的大多数偏差都会导致您的功能根本无法使用。在典型的实现中,您基本上替换了链接器级别的默认实现 - 即,现有函数具有某些特定的错位名称。如果你提供的函数的名称会变成相同的结果,那么它将被链接起来。如果你的函数没有变成同名,它就不会被链接。
您建议的模板在某些情况下可能会被使用,但如果是这样,则会导致未定义的行为。根据您排列标题的方式(例如),您最终可能会将模板与默认函数的使用混合在一起,此时您希望最好的是它会快速而干净地崩溃。