Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does =delete on destructor prevent stack allocation?

In this SO question is stated that this construct prevents stack allocation of instance.

class FS_Only {
    ~FS_Only() = delete;  // disallow stack allocation
};

My question is, how does it prevents allocation? I understand, that is not possible to delete this instance, either explicitly or implicitly. But I think, that would lead to memory leak or run time error, respectively.

Are compilers smart enough to sort this out and raise compiler error? Also why would one need this?

like image 319
jnovacho Avatar asked Sep 17 '13 10:09

jnovacho


People also ask

Does the destructor remove memory allocated to an object?

A destructor only destroys and cleans up the object. It does not deallocate the memory.

What does a destructor delete?

Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.

Can we use delete in destructor?

When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the object's memory is deallocated (if the object has a destructor). If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.

Are destructors are used to allocate memory?

Constructors and destructors are special member functions of classes that are used to construct and destroy class objects. Construction may involve memory allocation and initialization for objects. Destruction may involve cleanup and deallocation of memory for objects.


2 Answers

The destructor of a variable with automatic storage duration (i.e. a local variable) would need to run when the variable's lifetime ends. If there is no accessible destructor the compiler refuses to compile the code that allocates such a variable.

Basically the distinction between "stack allocation" (an inaccurate choice of term by the way) and free store allocation is that with local variables constructor/destructor calls always come in pairs, whereas with free store allocation you can construct an object without ever destructing it. Therefore by preventing access to the destructor your code makes it impossible to allocate a local variable of the type (if the constructor runs the destructor must also run, but there is no destructor so the program is rejected).

like image 105
Jon Avatar answered Sep 22 '22 21:09

Jon


I understand, that is not possible to delete this instance, either explicitly or implicitly.

More than that, it's not possible to destroy any instance; whether by deleting it or otherwise.

Declaring an automatic variable (or "stack allocation", if you like) doesn't just cause the instance to be created when the program reaches the point of declaration; it also causes it to be destroyed when the program leaves that block. With a deleted destructor, that can't be done, so the declaration is not allowed.

This also prevents you from declaring a static or thread-local variable, since that also generates code to destroy the variable when the program or thread ends.

So the only way to create one of these is with new, and once you've done that you can never destroy it. However, this doesn't altogether prevent stack allocation:

char memory[sizeof(FS_Only)] alignas(FS_Only);
FS_Only * not_fs = new (memory) FS_Only;

Also why would one need this?

In my view, you wouldn't. A mandatory memory leak is a horrible way to ensure that an object is never destroyed at the wrong time. Instead, use techniques such as RAII to manage any objects that need a dynamic lifetime, ensuring that they always have a well defined owner (or shared owners) responsible for deleting them after use. The smart pointers in the C++11 standard library are a good starting point.

like image 37
Mike Seymour Avatar answered Sep 21 '22 21:09

Mike Seymour