15

Why can I create an object of a class with private destructor on free store but not on the stack ?

For example this is illegal:

class Foo
{
public:
   explicit Foo( int );
   static void delete_foo(Foo* foo ) { delete foo; }
private:
   int x;
   ~Foo();
   Foo( const Foo& );
   Foo& operator=(const Foo& );
};

int main()
{
   Foo * fooptr = new Foo(5); // legal
   Foo::delete_foo( fooptr ); // legal 
   Foo foo(5); // illegal
}
CashCow
  • 30,981
  • 5
  • 61
  • 92
There is nothing we can do
  • 23,727
  • 30
  • 106
  • 194

5 Answers5

19

When you create it on the stack, it must be destroyed before the function can return. Presuming the function in question does not have access to the destructor, this is not allowed.

When you create it on the free store, it is left for other code, which has access to the destructor, to destroy it.

A member function of a class with a private destructor can create an instance on the stack. A static member function can even be called without a preexisting instance. There is probably no good reason to write such a thing, though.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • 1
    @Potatoswatter: it can be useful to force the user into accessing the object through a `friend` proxy. Seems limited though. – Matthieu M. Feb 07 '11 at 10:46
  • 1
    @Matthieu: Yes, I should have mentioned that. There are good reasons to write a private destructor. I only meant that seldom will a static member function create a temporary instance, or will such an object be placed on the stack at all. – Potatoswatter Feb 07 '11 at 10:50
  • The one exception is of course the common singleton implementation: `static Singelton& instance(); /*...*/ Singleton& Singleton::instance() { static theInstance; return theInstance; }` – MSalters Feb 07 '11 at 11:04
  • @MSalters: Ew, ew, ew, ew, ew, ew, ew. – GManNickG Feb 07 '11 at 11:05
  • 1
    @Potatoswatter: its destructor is nonetheless called though :) – Matthieu M. Feb 07 '11 at 12:38
10

Because an object with automatic storage* needs to be, well, automatically destructed. So the destructor needs to be available to call; if it's not, you can't have that type in automatic storage.

Contrarily, it's up to you to delete it when you allocate it dynamically. You can, of course, not do so.

*Objects here are, on "typical" platforms, commonly allocated on the stack.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
2

Because creating an object on the free store doesn't require a public destructor, but creating it on the stack does because the objects will be destroyed when it goes out of scope. You can create the object on the free store, but you cannot delete it, so you'll have a memory leak unless the object or a friend function destroys it.

Philipp
  • 48,066
  • 12
  • 84
  • 109
2

You can create one on the stack only in the scope that has access to the destructor. Therefore you could do so in a friend function or static member function of the class (or even a regular class member).

The end of the function for a local variable is responsible for deleting therefore must be able to call the destructor, albeit implicitly.

You can create one with new from anywhere if you have access to the appropriate constructor.

If you use it in a smart-pointer you must ensure where it gets deleted has access. This may vary for different smart-pointers, and for some you can provide a custom destructor which could be a static member of the class.

CashCow
  • 30,981
  • 5
  • 61
  • 92
0

Because you can then enforce that an object is always allocated dynamically i.e. with a new operator. To make that work you would need to implement a dispose() method that calls "delete this" before it returns. This makes it possible to create finalizing methods that are called before an object or a part of an object is destroyed and so can safely delete or disconnect instance members before virtual destructors chain is getting called.

  • That is more like an answer to [this other question](https://stackoverflow.com/questions/631783/what-is-the-use-of-having-destructor-as-private) about what the uses of private destructors are, rather than what the OP asked here about why mechanistically a private destructor prevents automatic instantiation. – underscore_d Sep 16 '18 at 12:01
  • Yes, the most upvoted answer provides the answer, I was indeed looking at it from "why would one need that?" point of view. – Valery Arkhangorodsky Sep 17 '18 at 14:40