#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class A
{
static int k;
public:
A(){k++ ; cout << "constructor : " <<k<< endl;};
~A(){k--; cout << "destructor : " << k <<endl;};
void show() { cout<<"current value of k = "<<k<<endl; }
};
int A::k = 0;
int main( )
{
vector<A> test;
test.push_back(A());
test.emplace(test.end(), A());
test[0].show();
cout<<test.size()<<endl;
return 0;
}
Output:
constructor : 1
destructor : 0
constructor : 1
destructor : 0
destructor : -1
current value of k = -1
2
destructor : -2
destructor : -3
Why has the destructor been called too many times, as it should have been called just twice since the constructor only gets called twice? How to avoid this situation?
The signal emission most probably creates a copy of the object (using default copy constructor - so pointers in both object point to the same thing!), so the destructor is called twice, once for your filtmp and second time for the copy. Up to this point signal is not connected to anywhere.
According to the linked question, this is because the destructor is called multiple times for the pointer member, a consequence of the copy constructor being called multiple times when copying, causing an attempted deallocation of memory already deallocated.
Why is the destructor being called three times?
The best way to not call a particular destructor is to not create an instance of that object to begin with. Failing that, take the code you don't want to run out of the destructor.
A compiler-generated copy constructor is being used, which doesn't increment k
.
Include that explicitly in your source code, and all will be well.
You're making copies, but your trace output doesn't show that (and your k
doesn't get incremented when it happens). So the "extra" destructor calls go with copy constructions.
You can remove one of the copies by using emplace
properly:
test.emplace(test.end());
// ^ no A() here; that would be like doing test.push_back(A(A()))
but you still have a copy in the push_back
itself.
Write a copy constructor so that your trace output accounts for those operations:
A(const A&) { k++; cout << "copy-constructor : " << k << endl; }
(I wouldn't bother with a move constructor, as that'll delete
the copy assignment operator and all hell will break loose.)
Finished code:
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class A
{
static int k;
public:
A() { k++; cout << "constructor : " << k << endl; }
~A() { k--; cout << "destructor : " << k << endl; }
A(const A&) { k++; cout << "copy-constructor : " << k << endl; }
void show() { cout << "current value of k = " << k << endl; }
};
int A::k = 0;
int main()
{
vector<A> test;
test.push_back(A());
test.emplace(test.end(), A());
test[0].show();
cout << test.size() << endl;
}
Output:
constructor : 1
copy-constructor : 2
destructor : 1
constructor : 2
copy-constructor : 3
copy-constructor : 4
destructor : 3
destructor : 2
current value of k = 2
2
destructor : 1
destructor : 0
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