I'm studying to understand class constructor and destructor. I have written a small console code to add one class instance in to a vector. All is nice and dandy, but what I fail to understand is, that adding one Object in to the vector triggers destructor twice. Why does this happen?
If I don't add any object, the vector doesn't trigger constructor or destructor on its own, so why it happens twice?
Can anyone explain why this happens?
#include <cstdio>
#include <vector>
class Test
{
private:
int value;
public:
Test()
{
printf("\nClass constructor triggered.");
};
~Test()
{
printf("\nClass desctructor triggered.");
}
};
int main()
{
std::vector<Test> container;
container.push_back( Test() );
return 0;
}
UPDATE: I added some more information to the class so that I get more specific output, however now I noticed that with each addition to the vector the move-construction and destructor calls increase. Are the amount of these calls tied to the amount of objects within the vector or what is happening? Am I having a leak? Sorry if too stupid questions. Below is the added code:
#include <cstdio>
#include <vector>
class Test
{
private:
int value;
public:
// Constructor
Test(int v=0)
{
value = v;
printf("\n\n%i", value);
printf("\nClass constructor triggered.");
};
// Copy-move constructor
Test(Test&&)
{
printf("\nClass move-constructor triggered.");
};
// Destructor
~Test()
{
value = 0;
printf("\nClass desctructor triggered.");
}
};
int main()
{
std::vector<Test> container;
container.push_back( Test(1) );
container.push_back( Test(2) );
container.push_back( Test(3) );
container.push_back( Test(4) );
printf("\n\nPushback complete!");
return 0;
}
Your vector contains a copy of the object you add to it through push_back(). The first destructor invocation is caused by the temporary you create being destroyed at the end of the full expression containing the call to push_back(). The second destructor is caused by the copy inside the vector being destroyed when the vector itself is destroyed.
You can convince yourself by adding a diagnostic to main():
int main()
{
std::vector<Test> container;
container.push_back( Test() );
printf("\nThis is before the vector is destroyed...");
return 0;
}
You can observe the output in this live example.
The copy which your vector contains is created by invoking the automatically-generated move constructor for your class (rather than using default construction), which is why you don't see a corresponding construction diagnostic.
If you defined your own move constructor (or copy constructor, as shown below) to emit a diagnostic, the output would be closer to what you'd expect:
Test(Test const&)
{
printf("\nCopy construction triggered.");
};
Again, live example.
Because you don't print every constructor invocation, you're missing out on move-constructor call. Your class, apart from the default constructor you've provided, has also implicitly generated move and copy constructors.
The vector stores a value, and that value has to be initialized in some way. Typically, this happens either via a move c-tor or copy c-tor, altough an object might also be created directly inside of the vector using e.g. emplace_back.
Try adding this:
Test(Test&&)
{
printf("\nClass move constructor triggered.");
};
to your class, it should change the output to something that makes more sense (I've also added a print at the end of main):
Live On Coliru
Class constructor triggered.
Class moveconstructor triggered.
Class desctructor triggered.
Out of main scope.
Class desctructor triggered.
The first destructor call destroys moved-out "empty" instance of your class, while the second one fires when the vector itself is destroyed.
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