I am having trouble figuring out why (it seems like) an object is being destructed twice.
If i create a object of a class (B) which contains an object of another class (A) and i copy this object. the copied object is destructed twice. Altough it looks like this. I am unable to figure out this output.
I have created the following (minimum?) example which seems to trigger my issue:
#include <stdio.h>
#include <stdint.h>
template <class T>
class A
{
public:
A()
{
myCtr = ++ctr;
printf("class A default Constructor - object id: %u\n", myCtr);
}
A(const A<T> &a2) {
myCtr = ++ctr;
printf("class A copy constructor - object id: %u\n", myCtr);
}
~A()
{
printf("class A destructor - object id: %u\n", myCtr);
}
void add(T item) {
/* Irrelevant */
}
private:
uint64_t myCtr;
static uint64_t ctr;
};
class B
{
public:
B() {
}
B(char * input, uint32_t len) {
for (uint32_t i = 0; i < len; i++)
{
characters.add(input[i]);
}
}
B(const B &b2) {
characters = A<char>(b2.characters);
}
~B() {
}
private:
A<char> characters;
};
template <class T>
uint64_t A<T>::ctr = 0;
int main(int argc, char *argv[]) {
B b1 = B((char *)"b1", 2);
B b2 = B(b1);
return 0;
}
This produces the following output:
class A default Constructor - object id: 1
class A default Constructor - object id: 2
class A copy constructor - object id: 3
class A destructor - object id: 3
class A destructor - object id: 3
class A destructor - object id: 1
object id 3 is destructed twice while object id 2 is not destructed at all.
I am using the following compiler: Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26429.4
In case you down vote. Please specify why. I will gladly try to improve my question.
The confusion comes from this line.
characters = A<char>(b2.characters);
A default generated assignment operator copies object 3 to object 2, including myCtr
.
myCtr
is not const
, so it may change during its lifetime. If you need a value to remain the same, make it const
.
Here is a version of your class that will behave the way you expect.
template <class T>
class A
{
public:
A()
: myCtr( ++ctr )
{
printf("class A default Constructor - object id: %u\n", myCtr);
}
A(const A<T> &a2)
: myCtr( ++ctr )
{
printf("class A copy constructor - object id: %u\n", myCtr);
}
A<T>& operator=(const A<T> &a2) {
// Copy what's needed from a2 here.
return *this;
}
~A()
{
printf("class A destructor - object id: %u\n", myCtr);
}
void add(T item) {
/* Irrelevant */
}
private:
const uint64_t myCtr;
static uint64_t ctr;
};
You need to follow the rule of 5. If you implement a non-trivial destructor, copy/move assign/construct, you must implement all 5, or give a good reason why not, or delete them.
You implemented destory and copy ctor. You neglected the other 3. Add them.
What more characters = A<char>(b2.characters);
your copy ctor calls a copy assignment. Which you don't track, which is why your count is off. You assign over the counter.
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