Reputation: 2604
While doing my programming assignments, I seem to be stumbling over basic C++ concepts. I found the bug in my program and it was caused by my destructor running more times than I expected. Here is a code sample demonstrating what I am doing wrong, down to the bare essentials.
#include <iostream>
using namespace std;
class A
{
public:
A(int num)
{
number = num;
cout << "A constructed with number " << number << ".\n";
}
~A()
{
cout << "A destructed with number " << number << ".\n";
}
private:
int number;
};
class B
{
public:
B(A pa)
: a(pa)
{
cout << "B constructor run.\n";
}
~B()
{
cout << "B destructor run.\n";
}
private:
A a;
};
int main()
{
A foo(7);
{
B bar(foo);
}
//Pause the program.
system("pause");
}
What I expect to happen is A foo(7);
allocates space on the stack for an A
object named foo
and call the constructor, passing 7
. It assigns 7
to number
and prints output indicating the the constructor ran. Now B bar(foo);
allocates space on the stack for a B
object named bar
and calls the constructor, passing foo
by value, which is just a container for an int
. The constructor assigns the A
parameter passed to it to it's own private data member a
, and prints output to the screen.
Now, when bar
goes out of scope at the closing curly brace, I expect bar
's destructor to be called, which prints output to the screen, then calls the destructor for its data members, namely A a
. That destructor prints output to the screen, and discards the int number
that it was containing.
What I expect the output should be:
A constructed with number 7.
B constructor run.
B destructor run.
A destructed with number 7.
//Destructors should be called in the reverse order of their construction right?
The actual output:
A constructed with number 7.
B constructor run.
A destructed with number 7. //This is unexpected.
B destructor run.
A destructed with number 7.
What is causing that extra destruction?
Upvotes: 4
Views: 1127
Reputation: 114
Obviously it comes from member data A a; of class B. I guess your doubt is that why not see any construct output from A, because it's constructed with default copy-ctor for class A, It's better to add one copy-ctor for class A, so that you will see the construct procedure.
A(const A& a)
{
number = a.number;
cout << "A copy-constructed with number " << number << ".\n";
}
Upvotes: 2
Reputation: 208323
Your B
constructor takes the A
object by value, which means that foo
is copied into the parameter pa
which then gets copied to the member a
. The compiler has been able to elide one of the copies (argument to the constructor), but the other one cannot be elided and there you have the second A
object that get's destroyed.
Upvotes: 3
Reputation: 121599
I hate it when people get cute with "foo" and "bar".
But I see two instances of "A" being constructed - one explicitly, the other implicitly by "B". And two destructors getting invoked.
What's not to like about this picture ;)?
Upvotes: 1
Reputation: 3678
because in class B, there has one member A a
so to destruct B object, first to call its member's destructor.
Upvotes: 0