Today I was wondering about c++ destructors so I wrote a small test program. That answered my original question but raised a new one which is:
The following program:
#include "stdafx.h"
#include <vector>
#include <iostream>
using namespace std;
class test
{
public:
int id;
vector<test> collection;
test(){}
test(int id_in){id = id_in;}
~test(){cout << "dying: " << id << "\n";}
};
int _tmain(int argc, _TCHAR* argv[])
{
{
test obj(1);
obj.collection.push_back(test(2));
obj.collection.push_back(test(3));
cout << "before overwrite\n";
obj = test(4);
cout << "before scope exit\n";
}
int x;
cin >> x;
}
produces the following output:
dying: 2
dying: 2
dying: 3
before overwrite
dying: 2
dying: 3
dying: 4
before scope exit
dying: 4
Why don't I see a destructor for my test object with id 1? If its destructor isn't called when it is overwritten, than what calls the destructors of the instances in its vector?
What is a destructor? Destructor is an instance member function which is invoked automatically whenever an object is going to be destroyed. Meaning, a destructor is the last function that is going to be called before an object is destroyed.
To explicitly call the destructor for an object, s, of class String, use one of the following statements: The notation for explicit calls to destructors, shown in the preceding, can be used regardless of whether the type defines a destructor. This allows you to make such explicit calls without knowing if a destructor is defined for the type.
The class's destructor is called, and the body of the destructor function is executed. Destructors for nonstatic member objects are called in the reverse order in which they appear in the class declaration.
Order of destruction When an object goes out of scope or is deleted, the sequence of events in its complete destruction is as follows: The class's destructor is called, and the body of the destructor function is executed. Destructors for nonstatic member objects are called in the reverse order in which they appear in the class declaration.
You violate the Rule of Three by creating a destructor, but no assignment operator.
From reading that, you can interpret your code as follows:
When the line
obj = test(4);
is compiled, a temporary instance of test
is created with id 4.
Then, the assignment operator is called. Since you did not provide one, the compiler generated one for you that looks like this:
test& operator=(const test& other)
{
id = other.id;
collection = other.collection;
return *this;
}
The id 1 is simply overwritten with the 4 from the temporary, and for the collection assignment, the assignment operator of std::vector
is called.
std::vector
's assignment operator deletes all previously contained elements, which is why you see
dying: 2
dying: 3
in your output. Finally, the temporarily created obj instance with id 4 is deleted, causing
dying: 4
to appear for the first time. When obj
goes out of scope, you see the
dying: 4
output once more.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With