Is it possible to have automatically generated destructors in C++? [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
Is it possible to have automatically generated destructors in C++?
It is too big burden to do it by ourselves all the time. Is it so hard
for the compiler to generate destructors? Can't it detect what is a "resource"
and release it in the destructor?

Certainly it is, and that's exactly what the language does. If you don't declare a destructor, then one will be generated for you: it will invoke the destructor of each member and base subobject.
You only need to write your own destructor if you're managing a resource that isn't released automatically; for example, a raw pointer to something that you allocated with new. You shouldn't need such a thing in most classes - use containers, smart pointers and other RAII types to manage these automatically for you.

It can't be detected accurately. Even if the compiler observes that you allocate a resource in the constructor or in some other function of the object, it doesn't necessarily follow that it should be released in the destructor. It all depends whether or not the object "owns" the resource.
Fortunately, C++ does provide a means for you to inform the compiler explicitly what resources the object owns. This means is called "smart pointers", and the types you should read about are shared_ptr and unique_ptr. You can avoid writing destructors by thorough use of smart pointers. The compiler generates a destructor that destroys all your data members, so if the data members are smart pointers then the resources they control are destroyed at the appropriate time.

Is it so hard for the compiler to generate destructors?
It is not a question of what is easy or hard for the compiler to do. It is a question of a fundamental tenet of C++ programming:
You shouldn't have to pay for what you don't need.
This philosophy prevails in every aspect of the design of the language, including how destructors are defined and work.
Every class needs a destructor of some kind. That's why the compiler automatically writes one for you if you don't do it yourself. This implicit destructor destroys all members and base classes in a specific order and in a specific way. Sometimes this isn't what you really want, but that compiler can't assume this. A classic case is with smart pointer classes. A smart pointer class will have a raw pointer to the controlled object somewhere, but the compiler doesn't know if that pointer should be deleted -- maybe you are implementing a reference-counter smart pointer. If you need the destructor to actually delete the pointer, that you have to write yourself.
Another case is with deleteing derived classes. Consider:
Base* p = new Derived;
delete p;
If Derived has a bunch of stuff in it which needs to be released, then you need to make sure that when you delete the Derived object through the Base pointer, Derived's destructor is the one that's actually called -- even though the compiler has no way of knowing at the call site that p actually points to a Derived. In order to make this work, you need to make Base::~Base a virtual destructor.

Neither C++ nor C++11 have garbage collection. C++11 does introduce a number of managed pointer classes in the memory header file--shared_ptr, weak_ptr and unique_ptr. These are designed to help prevent memory leaks. For an explanation see C++ Smart Pointers tutorial and Smart Pointers (Modern C++) on MSDN.

Related

What does the destructor of primitive types actually do? [duplicate]

This question comes from me trying to understand the motivation for smart pointers where you make a wrapper class around the pointer so that you could add a custom destructor. Do pointers (and ints, bools, doubles, etc.) not have a destructor?
Technically speaking, non-class types (C++ term for what often called 'primitive type' in layman words) do not have destructors.
C++ Standard only speaks of real destructors in context of classes, see [class.dtor] in C++ standard. Aside from that, C++ also allows to call a destructor on a non-class object using the same notation, i.e. following code is valid:
void foo(int z) {
using T = int;
z.~T();
}
This is called 'pseudo-destructor' and exists exclusively to allow writing generic templated code to deal in the same manner with class and non-class types. This call does nothing at all. This syntax is defined in [expr.prim.id] in C++ standard.
Primitive types (and compounds thereof) have trivial destructors. These don't do anything, and have special wording that allows them to be skipped altogether in some cases.
This, however, is orthogonal to why C++ has smart pointers. A raw pointer is non-owning: it points at another object, but does not affect its lifetime. Smart pointers, on the other hand, own (or share ownership of) their pointee, tying its lifetime to their own. This is what is implemented inside, among other special functions, their destructor.
In addition to the answers given here so far, since C++20 the pseudo-destructor call on a non-class object will always end its lifetime. Consequently accessing the object's value after the call will have undefined behavior. This does not mean however that the compiler has to emit any code for such a call. It still effectively does nothing.
No, pointers don't have destructors. An object referenced through a plain old pointer has to be deleted to avoid memory leaks, and the object's destructor is called then, but the compiler won't call delete automatically, even when a pointer goes out of scope - what if another part of your program also had a pointer to the same object?
Smart pointers aren't about calling a custom destructor, they're about ensuring that things get cleaned up automatically when they go out of scope. This 'cleaning up' might be deleting owned objects, freeing any malloced memory, closing files, releasing locks, etc.
Destructors are used to free the resources that an object may have used.
For pointers, you don't need delete if you are not allocating new memory from the heap.
C and C++ have two ways to store a variable: stack and heap.
Stack is for static memory, and the compiler takes care of that. Heap is for dynamic memory, and you have to take care of this if you are using it.
When you do primitive type declarations, stack memory is allocated for the variables.
When you use new to declare an object, this object is stored on the heap, which you need to delete it when you are finishing using it, or it would be a memory leak.
Basically, you only need delete if you new something.

Why is the syntax of the destructor ~classname? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 months ago.
Improve this question
The syntax of the destructor is ~classname. This results in the need to explicitly write the type of object in the destructor call. To avoid this, C++17 introduced std::destroy_at.
So, what was Bjarne Stroustrup's original rationale for choosing the ~classname syntax for the destructor? If the syntax does not depend on the types, std::destroy_at is not needed.
First of all, I am not sure about the initial rationale for ~ in ~T(). The thing is that most of the time it does not matter how the destructor is called manually.
Usually you never call a destructor explicitly. Most of your variables should use automatic storage:
{
foo x;
}
The destructor of x is called automatically when x goes out of scope. Explicitly calling the destructor of x is wrong, because once it goes out of scope it would be called again resulting in undefined behavior.
Sometimes you need dynamic allocation (do it via smart pointers, but for the point here manual is "ok"):
foo* p = new foo();
delete p;
You must delete what you created via new. Also here calling the destructor explicitly would be wrong, because delete calls the destructor and frees the allocated memory. Only calling the destructor will not free the memory and calling the destructor twice is undefined behavior.
The only case you have to call a destructor explicitly is when you allocate memory and create the object in two seperate steps via placement new: What uses are there for "placement new"?.
Placement new isn't something you use everyday. It is mainly found in libraries. It is a case where you need to call a destructor explicitly and that is the case when std::destroy_at can be handy.
Suppose you write this code:
void foo() {
auto x = returns_some_pointer();
// ....
... now delete *x ...
}
Suppose returns_some_pointer returns a pointer to some object. Further suppose that object has been created via placement new and at the end of foo we want to call its destructor. foo doesn't need to know the type of x for anything. To call the destructor it would need to know T to be able to call ~T(). The type can be deduced from x itself, but thats not very convenient. A very convenient way to deduce T is to use a function template, and that is destroy_at(x);.
TL;DR: For most cases it does not really matter how the destructor is called, because it will be either called automatically or under the hood by calling delete. std::destroy_at is not a replacement for the destructor, but rather a convenience method to deduce the type of the object whose destructor is to be called.
Constructors and destructors were a part of C++ from the very earliest days. (They predated the name "C++.") They predated templates as well as the standard container types like vector that templates made possible. In those early days there was little or no allowance for manual construction/destruction as a separate operation from new and delete (e.g. there was no placement-new). Nested classes were also not supported.
All in all, there was no question of ever needing to refer to the destructor except as part of its definition, and no question that there would be any doubt or complexity in forming the destructor's identifier.
Naming the constructor after the class fits with C's general tendency for declarations to resemble the usage of the things they declare (e.g. int *a(int b) results in something where *a(b) is well-formed). The destructor is conceptually linked to the constructor, so it would be weird for the class name to show up in the constructor but not the destructor. And with no support for operator overloading (at the time) beyond operator=, there was no question of confusing ~classname with an overloaded operator~. So it was a simple, low-stakes, mildly witty syntax detail.

Why does the deleting destructor occupy a second vtable slot besides the ordinary destructor?

In C++ ABI implementations modeled after the Itanium C++ ABI, which is followed by many ABIs for other processors, virtual destructors actually occupy two vtable slots. Besides the "complete object destructor", which does what you would expect, there is a second entry for the "deleting destructor", which calls the first, and then deletes the memory of the object.
There is a problem with this approach, which can be a nuisance in small memory systems: The dynamic memory manager is linked in, even when no other code uses it. This is dead code when there is no call to delete anywhere in the application. This is because the C++ compiler/linker usually isn't able to detect that a slot in the vtable isn't called from anywhere, and hence to remove the associated code. Clearly, it would be better if the deleting destructor could be implemented in a different way that doesn't involve a vtable entry, and allows the compiler/linker to omit this dead code.
One can of course implement a custom void operator delete(void *) {} to prevent the linker from bringing in the dynamic memory code, but this still doesn't prevent the deleting destructor code to be emitted entirely.
Hence my question: Is there no better way to implement deleting destructors? My idea would have been to return the pointer to the start of the memory block to delete from the complete object destructor. If the memory block is to be deleted after destruction, this returned address can be used by a nonvirtual function that calls operator delete. Essentially, having the memory address returned by the complete object destructor would allow the deleting destructor to be nonvirtual, and therefore eligible for dead code elimination.
But I guess I must have overlooked something, which makes that rather simple solution impossible. But what would that be? Can someone expound the the design decision in the Itanium ABI for me?
Edit: I have found information that provides a partial answer here:
The top answer contains this explanation:
When some class defines its own operator delete, the selection of a specific operator delete to call is done as if it was looked up from inside the class destructor. The end result of that is that for classes with virtual destructor operator delete behaves as if it were a virtual function (despite formally being a static member of the class).
Apparently, the way chosen by the Itanium API to make it behave like a virtual function, is to make the destructor that calls it an actual virtual function.
However, that is not the only way to implement it. The linked article centers around an implementation that uses a single virtual function with a hidden parameter, but that solution produces the same undesirable behaviour I was describing above. Another implementation might be to have the complete object destructor return the address of the operator delete() if there is a custom implementation for the class, and nullptr otherwise. This would avoid the problem I described above.
So, in a somewhat modified form, my question still stands.
Unlike normal virtual functions at destruction of a class, one has to call its destructor and destructors of all its parents in the correct order.
It is technically possible to unite all the function calls into a single function call but it would require knowledge of the implementation of each destructor or full structure of the object. Basically de-virtualizing the call. Compilers aren't good at it. Not too sure on all the details as it is quite complex question considering all the possible overly-virtual objects.

Do Primitive Types in C++ have destructors?

This question comes from me trying to understand the motivation for smart pointers where you make a wrapper class around the pointer so that you could add a custom destructor. Do pointers (and ints, bools, doubles, etc.) not have a destructor?
Technically speaking, non-class types (C++ term for what often called 'primitive type' in layman words) do not have destructors.
C++ Standard only speaks of real destructors in context of classes, see [class.dtor] in C++ standard. Aside from that, C++ also allows to call a destructor on a non-class object using the same notation, i.e. following code is valid:
void foo(int z) {
using T = int;
z.~T();
}
This is called 'pseudo-destructor' and exists exclusively to allow writing generic templated code to deal in the same manner with class and non-class types. This call does nothing at all. This syntax is defined in [expr.prim.id] in C++ standard.
Primitive types (and compounds thereof) have trivial destructors. These don't do anything, and have special wording that allows them to be skipped altogether in some cases.
This, however, is orthogonal to why C++ has smart pointers. A raw pointer is non-owning: it points at another object, but does not affect its lifetime. Smart pointers, on the other hand, own (or share ownership of) their pointee, tying its lifetime to their own. This is what is implemented inside, among other special functions, their destructor.
In addition to the answers given here so far, since C++20 the pseudo-destructor call on a non-class object will always end its lifetime. Consequently accessing the object's value after the call will have undefined behavior. This does not mean however that the compiler has to emit any code for such a call. It still effectively does nothing.
No, pointers don't have destructors. An object referenced through a plain old pointer has to be deleted to avoid memory leaks, and the object's destructor is called then, but the compiler won't call delete automatically, even when a pointer goes out of scope - what if another part of your program also had a pointer to the same object?
Smart pointers aren't about calling a custom destructor, they're about ensuring that things get cleaned up automatically when they go out of scope. This 'cleaning up' might be deleting owned objects, freeing any malloced memory, closing files, releasing locks, etc.
Destructors are used to free the resources that an object may have used.
For pointers, you don't need delete if you are not allocating new memory from the heap.
C and C++ have two ways to store a variable: stack and heap.
Stack is for static memory, and the compiler takes care of that. Heap is for dynamic memory, and you have to take care of this if you are using it.
When you do primitive type declarations, stack memory is allocated for the variables.
When you use new to declare an object, this object is stored on the heap, which you need to delete it when you are finishing using it, or it would be a memory leak.
Basically, you only need delete if you new something.

Class destructor memory handling in C++

What potential memory leaks won't an implicit destructor handle? I know that if you have anything stored on the heap it won't handle it, and if you have a connection to a file or a database, that needs to be handled manually. Is there anything else? What about, say, non-base data types like vectors?
Also, in an explicit destructor, need you destroy non-heap variables which would have been destroyed by the implicit, or are they handled automatically?
Thanks
vectors and the like will deallocate themselves because their destructor is called.
In fact your problem will lie with anything that would cause a problem of a dangling pointer (or handle or whatever), ie anything that needs to be manually Closed or de-allocated won't be in an implicit destructor. Anything that destructs itself properly will be fine. This is why the RAII idiom is so popular :)
I think the question is upside-down. Don't think in terms of what object destruction doesn't do: think in terms of what it does do.
If a class only has an implicit destructor, then when it is destroyed, all non-static data members are destroyed too, as are all base-class sub-objects.
You can argue a bit whether this is done "by the implicit destructor" or not - if you write a destructor, those things still happen. It's part of the object destruction process itself, rather than part of the code of the destructor as such.
So, if your "connection to a file" is a FILE* class member, then the default destructor doesn't release it, because FILE* is a C thing, and it doesn't have a destructor. Destroying a FILE* does nothing. If your "connection to a file" is a std::ofstream, then it does have a destructor, and the destructor tries to flush and close the connection.
Vector has a destructor which release the vector's resources. This means that in turn the elements in the vector have their destructors called.
For each member variable you have, you should look at the corresponding documentation to see how resources are handled for that type. Obviously with experience, you start to remember the answers.
If the member variable is a pointer, then the implicit destructor doesn't do anything with it. So if it points to heap-allocated memory, and this object holds the only pointer to that memory, then you need to free it to avoid a memory leak.
If you find yourself writing a destructor in C++ that needs to free more than one thing, then you've probably designed the class badly. There are almost certainly exception-safety errors elsewhere in the class: it's possible to get the code right, but if you're experienced enough to get it right then you're experienced enough to make your own life easier by designing it differently ;-). The solution is to write classes with a single responsibility -- to manage a single resource -- and use them as member variables. Or, better, to find library classes that manage the resource you're using. shared_ptr is pretty flexible.
"need you destroy non-heap variables"
There is no such thing in C++ as "heap" and "non-heap" variables. Destroying a pointer does not free the thing pointed to, for the obvious reason that nothing in the type of a pointer tells you how the thing it points to was allocated, or who "owns" it.
You need to understand three things about destructors. Say you have an object t of class T with three members.
class T
{
A a;
B b;
C c;
// ...
} t;
Destructing t ALWAYS means calling the following destructors in that order: ~T(), ~C(), ~B(), ~A(). You cannot influence these semantics. It is impossible to prevent the destruction of the members. This ALWAYS happens, no matter if you define ~T() manually or if the compiler generates it.
Implicitly generated destructors are ALWAYS a no-op. However, as stated in point 1, the destructors ~C(), ~B() and ~A() will still be executed afterwards.
The destructors of scalar types, especially C-style pointers, are ALWAYS a no-op. This is the sole reason why you almost always need to write the destructor (and the copy constructor and the assignment operator) manually when you have a C-style pointer member -- after ~T() has finished, destructing a C-style pointer member does NOTHING, so any cleanup intended on the pointees has to be done in ~T().
I hope this clears things up for you.
What potential memory leaks won't an implicit destructor handle? I know that if you have anything stored on the heap it won't handle it, and if you have a connection to a file or a database, that needs to be handled manually. Is there anything else? What about, say, non-base data types like vectors?
To put it simply, you are correct. The only thing not handled by the implicit destructor is memory allocated in the form of a pointer or another type of resource that needs to be released explicitly.
With regard to vectors or any other class type objects; all classes have a destructor which takes care of releasing their data. The destructor of an object of this type is called when it goes out of scope. All basic data types like: int, float, double, short, bool etc are released in similar fashion.
Also, in an explicit destructor, need you destroy non-heap variables which would have been destroyed by the implicit, or are they handled automatically?
The answer to this is that they are handled automatically, in fact you should never ever try to explicitly call the destructor of an object.
In an implicit destructor the following occurs:
Each of the member variables of the class have their destructors called in turn.
In an explicit destructor the following occurs:
The body of the explicit destructor is executed
Each of the member variables of the class have their destructors called in turn.
So you can see that an explicit destructor is much the same as an implicit one, except that you can take any necessary manual intervention.
Now as a bit of advice with regard to managing memory allocated objects you should pretty much always use RAII (resource acquisition is initialisation). The crux of this is smart pointers, these are pointers that are deleted correctly when they go out of scope just like non heap allocated objects. Ownership becomes an issue once you start using them but that's a story for another day. A good place to start with smart pointers is boost::shared_ptr. (btw if you haven't got on board with boost yet and you write c++ code do yourself a favour...)
The implicit destructor calls the destructor on all member variables.
If you have a raw pointer, its destructor does nothing. So if you own the memory it points to, you have to release it explicitly.
The same applies to any other resource, or any other action you wish to take not implied by the default destructor of the member variable.
The default destructors of members are still called, so vectors, auto_ptrs, files opened using std streams or other C++ libraries all get destroyed. The moral is to wrap any OS objects which need releasing in C++ classes which tidy themselves up, so that application classes don't have to worry about it.
A class' destructor will implicitely call the destructors of all non-static members, then the destructors of virtual base classes, then its own code.
If you have STL containers as class members, you don't have to do anything explicitely--they will free their own memory in their destructors.
You're already making wrong assumptions. If my class holds heap-allocated data using an std::auto_ptr<Data>, the implicit dtor will handle it. No memory will be leaked. The reason is that the implict dtor, like any other dtor, will call the dtors of all members and base classes.
Now, a good class design holds all important resources as members with proper dtors. As a result, the dtor body needs to do nothing to prevent resource leaks. Of course, there is one exception to that rule: resource managing classes themselves manage precisely one resource, and therefore clean up that one resource in their dtor.