Why a class has only one destructor? [duplicate] - c++

This question already has answers here:
Are destructors overloadable?
(3 answers)
Closed 9 years ago.
I have been asked a question as, a class has multiple constructors but why it has only one destructor?
I gave below example,
class abc
{
public:
int a;
abc()
{
cout << "Default\n";
}
abc(int)
{
cout << "Int\n";
}
~abc()
{
cout << "Destructor\n";
}
};
int main()
{
abc ab;
abc a(5);
}
And I explained as before abc a(5); gets called destructor will get called so, there will only one object at a particular point of time. I ran the above code now in my PC but it gave me output as
Default
Int
Destructor
Destructor
If this is so then why do we haveone destructor ?

A destructor doesn't have parameters, so there can be only one. However you can have more than 1 constructor since you can overload the constructor which is not possible with Destructors.
Also to add that destructor is used to terminate the instance of the class and release all resources which it is using. There is nothing optional when you are destroying the object. The instance will not exist when destructor will be called.
Although a very wierd example to explain it but its like if you have 1 Apple and 1 Guava then you will use the 1 knife to cut it. ;)
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.
before abc a(5); gets called destructor will get called
No it will not be called as Destructors are called implicitly.
On a side note:-
However if you plan to call the Destructor explicitly(which most of the programmers will not suggest) then it would be completely your responsibility to manage the resources. The compiler will not take care of it and it may result in serious memory issues. You may check this C++ FAQ explaining it.

The destructor cannot be overloaded because it doesn't take any parameters (nor has a return type).
Its purpose is to deallocate any objects from memory that the class is using from memory. Usually, you deallocate stuff here.
The thing is that the destructor will be called via the delete or the delete[] keyword which doesn't take in parameters. Any why should they? You want to destroy the whole object, not a part of it, anyway.

The idea is that there could be different way to construct and initialize an object, therefore there can be more than just one constructor, but there is only one way to destroy objects. The language does not allow customization of the destruction of objects. All objects of a type, regardless how they are created must be destroyed in the same way.

The constructor can be overloaded using various parameter but destructor cannot be overloaded as it does not contain parameters..
This is one main reason.
And logically speaking the, you are going to delete every thing in the destructor, hence there is in fact no need of a parameter to specify anything..

A destructor takes no arguments and has no return type. Its address cannot be taken. Destructors cannot be declared const, volatile, const volatile or static.
So you don't have to specify arguments you passed to the constructor when the object is created.

constructors can be overloaded but destructors can not be overloaded.
when an object is created, it's suitable constructor is automatically called for initializing the object. when the program is removed from memory the destructor for each object is called for removing these un referenced objects from the object pool. since destructor is the system routine for clearing the object pool.

Related

Caveats and risks of calling a constructor and destructor like common methods?

There's a point in my program where the state of a certain object needs to be reset "to factory defaults". The task boils down to doing everything that is written in the destructor and constructor. I could delete and recreate the object - but can I instead just call the destructor and the constructor as normal objects? (in particular, I don't want to redistribute the updated pointer to the new instance as it lingers in copies in other places of the program).
MyClass {
public:
MyClass();
~MyClass();
...
}
void reinit(MyClass* instance)
{
instance->~MyClass();
instance->MyClass();
}
Can I do this? If so, are there any risks, caveats, things I need to remember?
If your assignment operator and constructor are written correctly, you should be able to implement this as:
void reinit(MyClass* instance)
{
*instance = MyClass();
}
If your assignment operator and constructor are not written correctly, fix them.
The caveat of implementing the re-initialisation as destruction followed by construction is that if the constructor fails and throws an exception, the object will be destructed twice without being constructed again between the first and second destruction (once by your manual destruction, and once by the automatic destruction that occurs when its owner goes out of scope). This has undefined behaviour.
You could use placement-new:
void reinit(MyClass* instance)
{
instance->~MyClass();
new(instance) MyClass();
}
All pointers remain valid.
Or as a member function:
void MyClass::reinit()
{
~MyClass();
new(this) MyClass();
}
This should be used carefully, see http://www.gotw.ca/gotw/023.htm, which is about implementing an assignement operator with this trick, but some points apply here too:
The constructor should not throw
MyClass should not be used as a base class
It interferes with RAII, (but this could be wanted)
Credit to Fred Larson.
Can I do this? If so, are there any risks, caveats, things I need to remember?
No you can't do this. Besides it's technically possible for the destructor call, it will be just undefined behavior.
Supposed you have implemented the assignment operator of your class correctly, you could just write:
void reinit(MyClass* instance) {
*instance = MyClass();
}
You should use a smart pointer and rely on move semantics to get the behavior you want.
auto classObj = std::make_unique<MyClass>();
This creates a wrapped pointer that handles the dynamic memory for you. Suppose you are ready to reset classObj to the factory defaults, all you need is:
classObj = std::make_unique<MyClass>();
This "move-assignment" operation will call the destructor of MyClass, and then reassign the classObj smart pointer to point to a newly constructed instance of MyClass. Lather, rinse, repeat as necessary. In other words, you don't need a reinit function. Then when classObj is destroyed, its memory is cleaned up.
instance->MyClass(); is illegal, you must get a compilation error.
instance->~MyClass(); is possible. This does one of two things:
Nothing, if MyClass has a trivial destructor
Runs the code in the destructor and ends the lifetime of the object, otherwise.
If you use an object after its lifetime is ended, you cause undefined behaviour.
It is rare to write instance->~MyClass(); unless you either created the object with placement new in the first place, or you are about to re-create the object with placement new.
In case you are unaware, placement new creates an object when you already have got storage allocated. For example this is legal:
{
std::string s("hello");
s.~basic_string();
new(&s) std::string("goodbye");
std::cout << s << '\n';
}
You can try using placement new expression
new (&instance) MyClass()

On calling destructor for an object, it is called two times? [duplicate]

This question already has answers here:
Destructor being called twice when being explicitly invoked
(10 answers)
Closed 8 years ago.
On calling desctructor explicitly, it is executed two times. What's the reason for that?
#include <iostream>
using namespace std;
class A
{
public:
int x;
A() { cout << "A's constructor called " << endl; }
~A(){
cout<<"A's desctructor called "<<endl;
}
};
int main()
{
A a;
A b;
a.~A();
}
Output:
A's constructor called
A's desctructor called
A's desctructor called
Well, you called it for 'a', and then 'the language' called it again for 'a' when the object went out of scope. And then, of course, 'the language' called it for b. By 'the language', I mean, of course, the very basic rule that automatic-scope objects are constructed as their scope initialize, and destructed when their scope ends.
Using explicit calls to destructors is rarely a good idea.
You shouldn't call the destructor by hand, it will get called automatically when the object goes out of scope.
The only place to manually call destructors is when you're writing your own allocator, but that is quite an advanced topic, so the rule of thumb would be to never call the destructor by hand.
[basic.life]/8:
If a program ends the lifetime of an object of type T with […]
automatic (3.7.3) storage duration and if T has a non-trivial
destructor, the program must ensure that an object of the original
type occupies that same storage location when the implicit destructor
call takes place; otherwise the behavior of the program is undefined.
Hence we cannot explain the behavior of your program in general, but we could say "For your implementation a particular execution behaved as if the destructor was called two times."
When a variable goes out of scope, its destructor is implicitly called.
If the there is no object of the appropriate type there, the behavior is undefined. Typically the compiler generates code that would call the destructor and does so blindly, as that makes the 'defined behavior' path efficient and simple, and the 'undefined behavior' path is considered your fault.
So what you are seeing is a symptom of undefined behavior. Your call of the destructor does not mean the compiler will not try to destroy the object.
In fact, if your object was slightly more complex, it could easily lead to a crash.
Don't call the destructor of an object directly unless you used placement new (a variant of new that constructs an object and does not allocate any memory) or the equivalent on it, and don't use placement new unless you really know what you are doing.
There is another valid use, where you destruct and reconstruct in the same place, but that is dangerous, usually a bad idea, and hard to get right.

c++ Destructors, When and Where if Ever?

I can't help reading the bulk of forum posts on destructors and getting totally confused.
Some say to call the destructor (with delete) once for each call to new. Some say the destructor automatically gets called in a variety of circumstances i.e. when the pointer is reassigned, when the object goes out of scope. Some suggest the pointer going out of scope while being a return value where the object exists as a copy of its former self, (does this then need explicit destruction as it was originally created with a new?
There seems to be some suggestion that calling the same destructor more than once will corrupt memory so all delete calls should be partnered with *pointer = NULL; to avoid corruption. If not then some more advanced object management system would require implementing, or an iron-fisted rigour of ownership.
I can't seem to make any sense of discussions on calling sequence of destructors, i.e. does the call 1) originate at the base superclass and cascade down to the specific class, calling all virtualised destructors on the way, 2) originate at the instantiated class and move up to the superclass, or 3) originate at the particular cast the class has when it goes out of scope, then traverse both toward the instantiated and base class. Do cascading destructors
Ultimately I simply don't know strictly how or when to delete objects if ever, whether objects are responsible for deleting all objects they reference, how to cleanly handle a proper object-oriented deletion routine where an object is referenced multiple times, it's just a mess in my head. As you can see I can't really formulate a single solid question to ask, am really hoping someone can offer a clean and concise discussion of if not the single 'correct' approach, at least the industry best practice to object deletion.
There are 3 types of allocation for which destructors are called in different ways:
Automatic allocation
These objects reside in automatic memory (trivially, the stack):
int main()
{
A a;
//...
}
The destructor of a is automatically called when a goes out of scope (closing }).
Dynamic allocation
Objects reside in dynamic memory (the heap). They are allocated with new and in order for the dstructor to be called, you need to call delete:
int main()
{
A* a = new A;
delete a; //destructor called
}
In this case it was probably suggested you should assign NULL to a after the delete. There are two schools of thought regarding this (I personally wouldn't suggest it). The motivation would be that you could possibly call delete again on a and crash the program if you don't set it to NULL. Which is correct. But if you do call delete again, that's already a bug or something wrong in the logic, which shouldn't be masked by making the code appear to run correctly.
Static allocation
Objects reside in static memory. Regardless of where they are allocated, the destructor is automatically called when the program ends:
A a; //namespace scope
int main()
{
}
Here, As destructor is called when the program terminates, after main finishes.
The C++ language leaves memory management in the hand of the programmer, that is the reason for which you can find that level of confusion.
Repeating what Luchian Grigore said there are three main types of memory
automatic storage (stack)
dynamic storage (heap)
static storage
If you allocate an object in automatic storage the the object will be destroyed once the scope is terminated; for example
void foo() {
MyClass myclass_instance;
myclass_instance.doSomething();
}
in the above case when the function terminates myclass_instance is destroyed automatically.
If you instead allocate an object in the heap with new then it's your responsibility to call the destructor with delete.
In C++ also an object can have sub-objects. For example:
class MyBiggerClass {
MyClass x1;
MyClass x2;
...
};
those sub-objects are allocated in the same memory the containing object is allocated to
void foo() {
MyBiggerClass big_instance;
MyBiggerClass *p = new MyBiggerClass();
...
delete p;
}
in the above case the two sub-objects big_instance.x1 and big_instance.x2 will be allocated in automatic storage (stack), while p->x1 and p->x2 are allocated on the heap.
Note however that you don't need in this case to call delete p->x1; (compile error, p->x1 is not a pointer) or delete &(p->x1); (syntactically valid, but logical mistake because that it wasn't allocated explicitly on the heap, but as a sub-object of another object). Deleting the main object p is all that is needed.
Another complication is that an object may keep pointers to other objects instead of including them directly:
class MyOtherBigClass {
MyClass *px1;
MyClass *px2;
};
in this case it will be the constructor of MyOtherBigClass that will have to find the memory for the sub-objects and it will be ~MyOtherBigClass that will have to take care of destroying the sub-objects and freeing the memory.
In C++ destroying a raw pointer doesn't automatically destroy the content.
Base classes in simple cases can be seen just as hidden embedded sub-objects. I.e. it's like if an instance of the base object is embedded in the derived object.
class MyBaseClass {
...
};
class MyDerivedClass : MyBaseClass {
MyBaseClass __base__; // <== just for explanation of how it works: the base
// sub-object is already present, you don't
// need to declare it and it's a sub-object that
// has no name. In the C++ standard you can find
// this hidden sub-object referenced quite often.
...
};
This means that the destructor of the derived object doesn't need to call the destructor of the base object because this is taken care by the language automatically.
The case of virtual bases is more complex, but still the invocation of base destructors is automatic.
Given that memory management is in the control of the programmer there are a few strategies that have emerged to help programmers avoiding making a mess of intricate code that always ends up in object leaks or multiple destruction.
Plan carefully how you are going to handle lifetime of the instances. You cannot just leave this as an afterthought because it will be impossible to fix later. For every object instance it should be clear who creates and who destroys it.
When it's impossible to plan ahead of time when an object should be destroyed then use reference counters: for every object keep track how many pointers are referencing it and destroy the object once this number reaches zero. There are smart pointers that can take care of this for you.
Never keep around a pointer to an object that has already been destroyed.
Use containers that are classes designed explicitly to handle the lifetime of contained objects. Examples are std::vector or std::map.
If your code calls new, then it should call delete as well, yes. Except if you are using smart pointers (which will call delete for you when the pointer gets destroyed). Whenever possible, you should use smart pointers and use vector or string to avoid having to manually allocate memory using new - if you don't call new, you don't need to worry about making sure delete is called -> no memory leaks, and no problems with objects being destroyed at the wrong time, etc.
Calling delete multiple times for the same instance is definitely a bad idea.
If we have this:
class A
{
int *p;
public:
A() { p = new int[10]; }
~A() { delete [] p; }
};
class B
{
A a;
~B() { ... }
...
};
class C : public B
{
...
~C() { ... }
}
...
C *cp = new C;
....
delete cp;
then the destructor of C gets called by delete. The destructor of B is called by the C destructor, and the destructor of A gets called by the B destructor. This is automatic, and the compiler will "make sure this happens".
And if we don't call new:
...
{
C c;
...
} // Destructor for C gets called here (and B and A as describe above)

Does equal amount of constructor and destructor calls ensure no memory leaks?

Let's say we have a class called memoryCounter that tries to catch memory leaks caused by MyClass class.
class memoryCounter
{
public:
static int MyClassCount;
};
int memoryCounter::MyClassCount = 0;
Let's also say we put the following lines in the constructor and destructor of MyClass (and any other constructors that it has, assuming also that we don't modify the MyClassCount anywhere else outside the constructors/destructors):
MyClass()
{
memoryCounter::MyClassCount++;
}
virtual ~MyClass()
{
memoryCounter::MyClassCount--;
}
Now, can we be absolutely sure that if memoryCounter::MyClassCount contains zero, then all the memory we allocated this far was freed and there are no leaks? Or can there be a situation when the variable will contain zero, but there will be allocated memory that we did not free (please consider the situations where 'MyClass' is a base or derived class, too)?
No, you can't. There can be other constructors as well (copy-constructor at least). You don't count them.
Also you can't count the destruction of static variables so easy, because they are destructed after main exits
If the count is zero, then there are no instances of MyClass. It applies regardless of whether the MyClass object is a complete object, or a base class sub-object, or for that matter a member sub-object. That doesn't necessarily mean there are no memory leaks, since maybe MyClass itself leaks memory.
Something to watch out for is the default-generated copy constructor. You say to assume that "any other constructors that it has" increment your global count, but it's easy to miss the constructor that doesn't appear in the code. You could have applied the rule of three here - you define a destructor so you should have defined a copy constructor. Mind you, the rule also tells you define a copy assignment operator, which in this case is not needed.
Who says that only constructors allocate memory? If some non-constructor member function (static or not) allocates memory, and the destructor does not clean up properly, you have leaked that memory.
So, the answer is no. You have counted class instances created through the standard constructor. No more, no less.
You're assuming that MyClass (and anything derived from it) are correctly written. In particular, this leak won't be detected:
class BadClass : private MyClass
{
public:
BadClass() { int *x = new int(5); }
}
What your counter does is tell you that you've had one destruction for each construction, which means nobody has leaked any 'MyClass' objects.
But that's not the same as no memory leaks.

What is the mechanism through which destructors are called for stack-assigned objects?

How does C++ ensure that destructors are called for stack assigned objects? What happens to the destructor function (or a pointer to it) when I assign dynamic memory as follows:
class MyClass {
public:
~MyClass()
{
std::cout<<"Destructor called."<<std::endl;
}
MyClass()
{
std::cout<<"Constructor called."<<std::endl;
}
};
....................................................................
//Limit scope for example
{
MyClass instance;
}
The constructor and destructor are both called. What's going on here?
The compiler inserts a call to the destructor for the object at an appropriate position.
You wouldn't wonder why this
{
int i;
}
creates and destroys i automatically, would you? C++ does a lot to allow you to create types that behave just like built-in types. And just like with built-in types, in C++ (other than in, say, Java or C#), this
{
MyClass instance;
}
doesn't just define a reference that might be bound to null or some actual object. It creates an actual object.
Object creation comes in two steps: First (upon entering the scope) the raw memory is provided. Then (when the object definition is encountered) the constructor is called. For built-in types no constructor is called. If you don't initialize a built-in variable, it has a random value. (Actually it's whatever the bit pattern was at the memory provided in step #1.) Object deletion, too, comes in two steps: First, the destructor is called (again, not for built-ins), then the memory is returned to the run-time system.
(Note that providing and deleting memory for stack variables usually is as cheap as incementing/decrementing a register.)
The constructor is called as soon as the variable is created. As for the destructor, the compiler emits code at the end of scope to call the destructor. To get a feel for this, try using a 'goto', or switch/case construct to prematurely exit the scope, and watch the compiler complain.
Yes, both the constructor and destructor are called. And even more important:
{
MyClass instance;
throw "exception";
}
in this example, the destructor is also called. That is why I always prefer to allocate my objects on stack (or at least wrap the dynamic allocations with a stack-allocated guardians).
The constructor is called because you're creating an object. The destructor is called because your cleaning up that object. Remember, in C++, objects declared on the stack are automatically cleaned up when their containing scope goes away.
Well, it did not call the destructor just after constructor.
It calls it when it about to terminate the programme.
int main() {
MyClass obj;
cout<<"testing....1"<<endl;
cout<<"testing....2"<<endl;
return 0;
}
ans:
Constructor called.
testing....1
testing....2
Destructor called.