Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can the global new operator be overridden based on allocated object's type traits?

I'm experimenting with upgrading our pooled fixed-block memory allocator to take advantage of C++11 type traits.

Currently it is possible to force any allocation of any object anywhere to be dispatched to the correct pool by overriding the global new operator in the traditional way, eg

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);
}

In many cases we could improve performance further if objects could be dispatched to different pools depending on type traits such as is_trivially_destructible. Is it possible to make a templatized global new operator that is aware of the allocated type, not just a requested size? Something equivalent to

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
}

Overriding the member new operator in every class won't work here; we really need this to automatically work for any allocation anywhere. Placement new won't work either: requiring every alloc to look like

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

is too cumbersome and people will forget to use it.

like image 422
Crashworks Avatar asked May 24 '13 23:05

Crashworks


People also ask

Which operators Cannot be overridden?

Operators that cannot be overloaded in C++ For an example the sizeof operator returns the size of the object or datatype as an operand. This is evaluated by the compiler. It cannot be evaluated during runtime. So we cannot overload it.

Can we override new operator in C++?

The new and delete operators can also be overloaded like other operators in C++. New and Delete operators can be overloaded globally or they can be overloaded for specific classes.

Can we resize the allocated memory which was allocated using the new operator?

Once the memory is allocated using the new operator, then it cannot be resized. On the other hand, the memory is allocated using malloc() function; then, it can be reallocated using realloc() function. The execution time of new is less than the malloc() function as new is a construct, and malloc is a function.

Can you override operators in Java?

Java doesn't supports operator overloading because it's just a choice made by its creators who wanted to keep the language more simple. Every operator has a good meaning with its arithmetic operation it performs. Operator overloading allows you to do something extra than what for it is expected for.


1 Answers

The short answer is no. The allocation/deallocation functions have the following signatures:

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

Most deviations from these signatures will result in your function not being used at all. In a typical implementation you're basically replacing the default implementations at the linker level -- i.e., the existing function has some particular mangled name. If you provide a function with a name that mangles to an identical result, it'll get linked instead. If your function doesn't mangle to the same name, it won't get linked.

A template like you've suggested might get used in some cases, but if so, it would lead to undefined behavior. Depending on how you arranged headers (for example) you could end up with code mixing the use of your template with the default functions, at which point about the best you could hope for would be that it crash quickly and cleanly.

like image 114
Jerry Coffin Avatar answered Sep 30 '22 20:09

Jerry Coffin