R@M3$H.NBlog

Limit the creation of object on Stack

26 January, 2013 - 2 min read

You can prevent an object being declared with automatic duration ("on the stack") by making its constructor private and providing a factory (abstract factory or factory method) to control creation of new objects.

To prevent accidental creation on the stack, make all constructors private, and/or make the destructor private, and provide friend or static functions that perform the same functionality.

Use the [Named Constructor Idiom](http://www.parashift.com/c++-faq-lite/named-ctor-idiom.html "[10.8] What is the "Named Constructor Idiom"?").

As usual with the Named Constructor Idiom, the constructors are all private or protected, and there are one or more public static create() methods (the so-called "named constructors"), one per constructor. In this case the create() methods allocate the objects via new. Since the constructors themselves are not public, there is no other way to create objects of the class.

class Fred {
public:
  // The create() methods are the "named constructors":
  static Fred* create()                 { return new Fred();     }
  static Fred* create(int i)            { return new Fred(i);    }
  static Fred* create(Fred const& fred) { return new Fred(fred); }
  ...

private:
  // The constructors themselves are private or protected:
  Fred();
  Fred(int i);
  Fred(Fred const& fred);
  Fred& operator= ( const Fred& fred) ;
  ...
};

Now the only way to create Fred objects is via Fred::create():

int main()
{
  Fred* p = Fred::create(5);
  ...
  delete p;
  ...
}

Make sure your constructors are in the protected section if you expect Fred to have derived classes.

To prevent an object from being allocated on the stack define a private destructor. This results in a compilation error for a stack based object, as it prohibits the implicit destructor call when a stack based object goes out of scope. You will need to implement a public destroy method, something along the lines of:

void MyObject::destroy() const
{
   delete this;
}