Allowing only dynamic object creation on heap
February 5, 2013
Which of the two comparison is better
February 6, 2013

Disallowing object creation on heap

Object of a class can be created dynamically on heap or statically on Stack or Data Area. If we have a class MyClass, then the below objects will be created on heap.

// Operator: New
MyClass *ptr1 = new MyClass(); // Crating object of MyClass on heap.
// Operator: New-Array
MyClass *ptr2 = new MyClass[10]; // Create an array of object MyClass on heap.

However, objects can also be created statically as below:

// Global object created at load time in the data area
MyClass obj1;
void func()
{
    // Object getting created on the Stack
    // (Activation record of function func).
    MyClass obj2;
    // Global object created at load time in the data area
    static MyClass obj3;
}

Design a class which does not allow any object to be created on heap.

Solution:

We have discussed earlier on “How to allow object creation only on heap“. This problem is the opposite of that post. So essentially, the requirement is that when a user tries to create an object using new or new[] operator then compiler should give an error.

That is, for a class “MyClass”, The below code should give error:

MyClass *ptr1 = new MyClass; // Should give Error
MyClass *ptr2 = new MyClass[5]; // Should give Error

But the below code should be allowed

MyClass obj;

1. Disallowing new operator

The first thought is to overload new operator and make it private.

class MyClass {
private:
  void* operator new(size_t size);
};

So that user will not be able to call new from outside. But, In this case the new[] operator will not give any error:

MyClass *ptr1 = new MyClass;  // ERROR. Call operator new
MyClass *ptr2 = new MyClass[5]; // Ok. Calls operator new[]

2. Disallow new[] operator

Ok, so the next step is to also overload the new-array operator inside the class and make it private

class MyClass {
private:
  void* operator new(size_t size);
  void* operator new[](size_t size);
};

It looks like complete, but there is still a catch. C++ allows placement new operator also. Hence also overload the corresponding placement new operators and make them private:

3. Disallowing placement-new and placement new array operators

class MyClass {
private:
    void* operator new(size_t size);          // standard new
    void* operator new(size_t size, void*);   // placement new
    void* operator new[](size_t size);        // array new
    void* operator new[](size_t, void*); // placement array new
};

Ok, so now we are done. Wait, can I not call the new operator from within the class.

Class MyClass{
public:
    MyClass(){
        MyClass *ptr = new MyClass(); // can call new operator
    }
    ...
    ...
};

This means that we have restricting the object creation on heap from outside the class only, but not from within the class. This is a problem, because according to the question, we should disallow all object creations on heap.

4. Disallow object creation from within the class

If we just declare the functions (new, new[], placement-new and placement new[]). But does not define them, then the linker will give error during the linking phase (when it will try to find definition of function new etc.).

Class MyClass{
public:
    MyClass();
private:
    // Only declaring them and not defining them in .cpp
    void* operator new(size_t size);
    void* operator new(size_t size, void*);
    void* operator new[](size_t size);
    void* operator new[](size_t, void*);
};

All the four functions are declared in the .h file but are not defined. Hence, one of the two case will come

1. Call the new operator from outside the class: Compile-time Error because operator functions are private and hence cannot be called from outside.
2. Call the new operator from within the class: Link-time Error, because the definition of function is missing.

Yeah, C++ is a funny language :).

Leave a Reply

Your email address will not be published. Required fields are marked *