8

我正在尝试升级我们的池化固定块内存分配器以利用 C++11 类型特征。

目前,可以通过以传统方式覆盖全局 new 运算符来强制将任何对象的任何分配分配到正确的池中,例如

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. 是否可以创建一个模板化的全局 new 运算符,它知道分配的类型,而不仅仅是请求的大小?相当于

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
}

在每个类中覆盖 member new 运算符在这里不起作用;我们真的需要它来自动为任何地方的任何分配工作。Placement new 也不起作用:要求每个 alloc 看起来像

Foo *p = new (mempool<Foo>) Foo();

太繁琐,人们会忘记使用它。

4

1 回答 1

3

最简洁的答案是不。分配/解除分配函数具有以下签名:

void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);

大多数与这些签名的偏差都会导致您的函数根本不被使用。在典型的实现中,您基本上是在链接器级别替换默认实现——即,现有函数具有一些特定的重命名。如果您提供的函数名称与相同的结果不一致,则它将被链接。如果您的函数不使用相同的名称,它将不会被链接。

在某些情况下可能会使用您建议的模板,但如果是这样,它将导致未定义的行为。根据您安排标题的方式(例如),您最终可能会使用将模板与默认函数混合使用的代码,此时您所希望的最好的结果就是它快速而干净地崩溃。

于 2013-05-25T00:16:25.383 回答