Consider the below code:
#include <iostream>
struct Person {
Person() { std::cout << "A"; } // Constructor
Person(const Person& other) { std::cout << "B"; } // Copy constructor
~Person() { std::cout << "D"; } // Destructor
};
struct Student : public Person { // Correct inheritance
Student() { std::cout << "a"; } // Constructor
Student(const Student& other) : Person(other) { std::cout << "b"; } // Copy constructor
~Student() { std::cout << "d"; } // Destructor
};
int main() {
Student* s1 = new Student; // Create Student object on heap
Student s2 = *s1; // Call copy constructor
*s1 = s2; // Use copy assignment operator
delete s1; // Delete the dynamically allocated memory
return 0;
}
The output is AaBbdDdD
. I do not understand why the destructor is seemingly called twice in this example. Could you please explain this to me?
The short explanation is that two objects are created and the same two are destroyed, resulting in destruction of two objects.
In more detail, I'll step through your main()
.
Firstly,
Student* s1 = new Student;
dynamically allocates a Student
(which calls constructors of Person
and Student
in order) and s1
is initialised to point at that object. Then ....
Student s2 = *s1;
creates a second object named s2
, and initialises it as a COPY (using copy constructor) of the object pointed to by s1
.
The next statement
*s1 = s2;
assigns the object pointed to by s1
to become a copy of the distinct object s2
. This statement neither creates nor destroys a Student
, so no constructor and no destructor are called.
The statement
delete s1;
then explicitly destroys the object pointed to by s1
. One step in destroying that object is a call of the destructor (the first destructor call you observe).
main()
then returns so all objects of automatic storage duration defined within main()
are automatically destroyed. Hence s2
is destroyed and, in that process, it's destructor called. That is the second destructor call you observe.