Question

I want to overload the operator new[] to get the number of how many objects are to be created. the best possible solution is to overload new[] in a way that the when creating an object using new[] would not necessitate the caller to write any extra code. i.e using simply:

Myclass objectsArray = new Myclass[5];

example overload:

class Myclass
{
 ...
public:
void* operator new[](size_t size)
{
   int numberOfObjects = figure out how to get number of objects to be created by this call to new[]
   std::cout << "requesting: " << numberOfObjects << " objects" << std::endl;
   void * temp = malloc(size) ;  
   return temp ; 
}
...
}

the following example program:

Myclass objectsArray = new Myclass[4];

would output:

requesting: 4 objects

edit: I want to do this just in MyClass not globaly

edit: I'm on ‎Lubuntu 12.0 with GCC version 4.8.1

edit: Purpose of the question:

I'm using a custom memory pool allocator that can't allocate arrays out of the box. so I need to know how many objects are requested and create them one by one using a loop with the pool allocator.

Was it helpful?

Solution

You need to define a class-specific operator new. This works for me, but beware of alignment, derived classes sizes, and allocation overhead issues in the count/sizeof(MyClass) expression:

#include <iostream>
#include <memory>
#include <new>

struct MyClass {
    int dummy[8];
    void *operator new[](std::size_t count) {
        std::cout << "allocating " << count << " bytes, " << ((count-sizeof(void*))/sizeof(MyClass)) << " items\n";
        return ::operator new[](count);
    }
};

int main() {
  auto x = std::make_unique<MyClass[]>(10);
}

(prints: allocating 10 items) I think one can determine the exact overhead for your compiler/stdlib combination empirically by doing something like:

#include <iostream>
#include <memory>
#include <new>

struct MyClass {
  char c;
  char d;
    virtual ~MyClass() {} // needed for introducing overhead
    void *operator new[](std::size_t count) {
        void *p = ::operator new[](count);
        std::cout << "allocating " << count << " bytes\n";
        return p;
    }
};

int main() {
  for( auto count : { 1, 5, 10, 20 } ) {
    std::cout << "allocating " << sizeof(MyClass) << " * " << count << " items\n";
    auto x = new MyClass[count];
    delete[] x;
  }
}

This will print, in my machine (and on Coliru):

allocating 16 * 1 items allocating 24 bytes, 1 items allocating 16 * 5 items allocating 88 bytes, 5 items allocating 16 * 10 items allocating 168 bytes, 10 items allocating 16 * 20 items allocating 328 bytes, 20 items

So, our count/sizeof(MyClass) (here) should be something like

(count-sizeof(void*))/sizeof(MyClass)

But YMMV, etc.

LAST EDIT (I hope)

I had success on 64-bits linux (clang-3.4, clang-3.5 & gcc-4.8, libstdc++ & libc++) with the following how_many_elements function:

template<class T>
    std::size_t how_many_elements(std::size_t bytes) {
  return (bytes -
    ((!std::is_trivially_destructible<T>::value)*sizeof(void*))
    ) / sizeof(T);
}

So your operator new becomes something like:

void *operator new[](std::size_t count) {
    std::cout << "allocating " << count << " bytes, " << how_many_elements<MyClass>(count) << " items\n";
    return ::operator new[](count);
}

But I have not tested it in 32-bits environments and the YMMV still applies. And remember to replicate the operator new for every derived class of MyClass, obviously replacing MyClass for MyDerivedClass or whatever...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top