More C++ Idioms/Requiring or Prohibiting Heap-based Objects

= Requiring or Prohibiting Heap-based Objects =

Intent

 * Require or prevent creation of objects on heap

Motivation
C++ supports different ways to create objects: stack-based (including temporary objects), heap-based, and objects of static storage duration (e.g., global objects, namespace-scope objects). Sometimes it is useful to limit the ways in which objects of a class can be created. For instance, a framework may require users to create only heap-based objects so that it can take control of the lifetime of objects regardless of the function that created them. Similarly, it may be useful to prohibit creation of objects on the heap. C++ has idiomatic ways to achieve this.

Solution and Sample Code
Requiring heap-based objects

In this case, programmers must use   to create the objects and prohibit stack-based and objects of static duration. The idea is to prevent access to one of the functions that are always needed for stack-based objects: constructors or destructors. Preventing access to constructors, i.e., protected/private constructors will prevent heap-based objects too. Therefore, the only available way is to create a protected destructor as below. Note that a protected destructor will also prevent global and namespace-scope objects because eventually the objects are destroyed but the destructor is inaccessible. The same is applicable to temporary objects because destroying temporary objects need a public destructor.

Protected destructor also prevents access to  because it internally invokes the destructor. To prevent memory leak,  member function is provided, which calls   on itself. Derived classes have access to the protected destructor so  class can still be used as a base class. However, the derived class no longer has the same restrictions.

Prohibiting heap-based objects

Dynamic allocation of objects can be prevented by disallowing access to all forms of class-specific  operators. The  operator for scalar objects and for an array of objects are two possible variations. Both should be declared protected (or private) to prevent heap-based objects.

The above declaration of protected  operator prevents remaining compiler-generated versions, such as placement new and nothrow new. Declaring just the scalar  as protected is not sufficient because it still leaves the possibility of   open. Protected  operator prevents dynamic allocation of arrays of all sizes including size one.

Restricting access to the  operator also prevents derived classes from using dynamic memory allocation because the new operator and delete operator are inherited. Unless these functions are declared public in a derived class, that class inherits the protected/private versions declared in its base preventing dynamic allocation.