Xeenych Xeenych
Xeenych Xeenych

Reputation: 195

Strange behaviour of a class destructor in C++

#include <iostream>
using namespace std;

class CCC {
public:
    CCC() {cout<<"created "<<++count<<endl;}
    ~CCC(){cout<<"deleted "<<--count<<endl;}
    int count=0;
};

CCC a;

CCC& create() { 
    return a; 
}

int main () {
    CCC result = create();
}

https://godbolt.org/z/K3eR9t

The above code produces strange output. Looks like the destructor is called 2 times, but count is not decremented. Why is that?

created 1
deleted 0
deleted 0

Upvotes: 2

Views: 147

Answers (4)

stena
stena

Reputation: 785

This is because of the implicitly defined copy constructor. It will copy the state of the other class by default, like: CCC(const CCC& other): count(other.count)

For a full example see below.

#include <iostream>
using namespace std;

class CCC {
public:
    CCC() {cout<<"created "<<++count<<endl;}
    CCC(const CCC& other): count(other.count) {cout<<"copied " << count << " others count " << other.count << endl;} 
    ~CCC(){cout<<"deleted "<<--count<<endl;}
    int count=0;
};

CCC a;

CCC& create() { 
    return a; 
}

int main () {
    CCC result = create();
}

https://godbolt.org/z/YM36ax

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310960

In this statement

CCC result = create();

there was used the default copy constructor.

So the object result has the same value of the data member count as the global object a.

Then destructors for the both objects were called decreasing corresponding data members count.

It seems what you are trying to do is either the following

#include <iostream>
using namespace std;

class CCC {
public:
    CCC() {cout<<"created "<<++count<<endl;}
    CCC( const CCC & ) {cout<<"created "<<++count<<endl;}
    ~CCC(){cout<<"deleted "<<--count<<endl;}
    int count = 0;
};

CCC a;

CCC& create() { 
    return a; 
}

int main () {
    CCC result = create();
}

and the program output is

created 1
created 1
deleted 0
deleted 0

or the following

#include <iostream>
using namespace std;

class CCC {
public:
    CCC() {cout<<"created "<<++count<<endl;}
    CCC( const CCC & ) {cout<<"created "<<++count<<endl;}
    ~CCC(){cout<<"deleted "<<--count<<endl;}
    static int count;
};

int CCC::count = 0;

CCC a;

CCC& create() { 
    return a; 
}

int main () {
    CCC result = create();
}

In this case the program output is

created 1
created 2
deleted 1
deleted 0

Upvotes: 3

Brian Bi
Brian Bi

Reputation: 119144

The count member is non-static, so each instance of CCC has its own copy.

For the instance a, the count member will be set to 0 when the default constructor starts, then incremented to 1 and printed. Later it will be destroyed, the count member decremented to 0, and printed again.

For the instance result, the count member is set to 1 by the copy constructor since it was 1 in a. When it is destroyed, the member is decremented to 0 and printed again.

If you wanted to track the total number of instances of the class that exist, you would need a static member,

static int count = 0;

Furthermore, you would need to increment it not only in the default constructor, but also in the copy and move constructors.

Upvotes: 7

w08r
w08r

Reputation: 1804

There are different types of constructor. You have instrumented the default constructor, but not the copy or move constructor. Please read up on the c++ rule of 3 / rule of 5 for more information.

Upvotes: 1

Related Questions