Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, preventing class instance from being created on the stack (during compiltaion)

I know there are methods to prevent a class from being created on the heap, by preventing the user from using the new and delete operator. I am trying to do just the opposite. I have a class that I want to prevent the user from creating an instance of it on the stack, and that only instances instigated using the new operator will compile. More specifically, I want the following code to receive an error during compilation:

MyClass c1; //compilation error

MyClass* c1 = new MyClass(); //compiles okay

From searching the web, I found this suggestion on how to do it:

class MyClass {
public:
    MyClass();
private:
    void destroy() const { delete this; }

...

private:
    ~MyClass();
};

int main(int argc,char** argv)
{
    MyClass myclass; // <--- error, private destructor called here !!!

    MyClass* myclass_ptr = new MyClass;
    myclass_ptr->destroy();
}

What I don't understand is why this should work. Why would the destructor be called while creating an instance of MyClass?

like image 559
eladidan Avatar asked Jun 22 '10 10:06

eladidan


People also ask

How do you stop an object from creation in C++?

But, we want to allow an object of the class to be created. To solve this problem, we can have a static function in the class that is called by class name without creating an object. And this function will create the class object, and return to users or main program.

How do I limit the number of instances of a class?

METHOD 1: Mutex as a Named Object So, named mutexes can be used to limit the number of instances running of a given application. The following code is to be placed in the WinMain function (or in the InitInstance method if MFC is on):

How objects and classes are defined and accessed in C ++?

An Object is an instance of a Class. When a class is defined, no memory is allocated but when it is instantiated (i.e. an object is created) memory is allocated. Defining Class and Declaring Objects. A class is defined in C++ using keyword class followed by the name of class.


2 Answers

When myclass reaches the end of its scope (the next }) the compiler calls the destructor to free it from the stack. If the destructor is private, however, then the destructor cannot be accessed, so the class cannot be placed on the stack.

I don't like the look of delete this. In general I think objects should not destroy themselves. Perhaps a better way is to have a private constructor for your class then use a static function to create an instance.

// In class declaration...
static MyClass* Create()
{
    return new MyClass(); // can access private constructor
}

// ...

MyClass myclass; // illegal, cannot access private constructor

MyClass* pMyClass = MyClass::Create();
delete pMyClass; // after usage
like image 81
AshleysBrain Avatar answered Nov 11 '22 12:11

AshleysBrain


Why would the destructor be called while creating an instance of MyClass?

It isn't. It must be invoked automatically when the instance goes out of scope, though. If it's private, the compiler must not generate that code, hence the error.

If you think making the destructor private is obscure, another way to restrict a class to dynamic allocation is to make all the constructors private and only have MyClass::create() functions returning dynamically allocated objects:

class MyClass {
public:
  static MyClass* create()             {return new MyClass();}
  static MyClass* create(const Foo& f) {return new MyClass(f);}
private:
  MyClass();
  MyClass(const Foo&);
};

Note that returning naked pointers to objects that must be deleted is frowned upon. You should return smart pointers instead:

class MyClass {
public:
  static std::shared_ptr<MyClass> create()             {return new MyClass();}
  static std::shared_ptr<MyClass> create(const Foo& f) {return new MyClass(f);}
  // ...
};
like image 28
sbi Avatar answered Nov 11 '22 10:11

sbi