#include <iostream>
#include <vector>
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
};
int main()
{
std::vector<A> myvec;
myvec.push_back(A());
myvec.push_back(A());
myvec.clear();
return 0;
}
output:
constructor
destructor
constructor
destructor
destructor
destructor
destructor
There are five calls to the destructor here. The first two are due to the temporaries which are passed to push_back
. There are three other calls, but I expected one two extra calls.
myvec.clear()
will clear only two contents so destructor of A
should call only two times (instead of three). why there is one extra time destructor is called?
But, if I push_back only one element to the vector, instead of two, the output is as I expected.
The call to std::vector::clear
isn't really important in this context because, when myvec
goes out of scope, its contents will be destroyed anyway.
Let's consider
class A
{
public:
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
A (const A &) { std::cout << "A(A&)\n"; }
};
int main()
{
std::vector<A> myvec;
std::cout << "First\n";
myvec.push_back(A());
std::cout << "Second\n";
myvec.push_back(A());
std::cout << '\n'; // to separate the final destruction
myvec.clear();
}
which outputs
First
constructor <-- First A _temporary_ object created when pushing_back
A(A&) <-- vector makes a *copy* of the temporary
destructor <-- Temporary A is destroyed
Second
constructor <-- Second A _temporary_ object created when pushing_back
A(A&) <-- Reallocation happens: vector can't copy because it ran out of space
A(A&) <-- Copy of the second temporary
destructor <-- Destroy of the temporary
destructor <-- Destroy of the first element
destructor
destructor
If you std::vector::reserve
some space, you can get rid of the copies made by the reallocation
std::vector<A> myvec;
myvec.reserve(8);
which confirms what said
First
constructor
A(A&)
destructor
Second
constructor
A(A&)
destructor
push_back
is still making copies of the parameter: this can be further optimized by making your class moveable.
A(A&&) noexcept = default;
A& operator=(A&&) noexcept = default;
First
constructor
destructor
Second
constructor
destructor
This is most likely due to the reallocation that takes place between the first and the second push_back
. If you reserve
some space ahead of time, then the deallocations are going to be 2
after the two push_back
s, as you have expected.
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