4

I'm doing an exercise and I cannot understand why the following code returns:

Program start, before f() -- number of objects: 0
After f(), before g()     -- number of objects: 0
After g(), before h()     -- number of objects: -1
After h(), program end    -- number of objects: -1

There is nothing wrong with f() and I understand everything happening there. However, I cannot figure out how the constructor and the destructor are called in g() and h(). Thank :)

Code:

class Counted {
public:
    Counted();
    ~Counted();
    static int getNbrObj();
private:
    static int nbrObj;
};

int Counted::nbrObj = 0;

Counted::Counted() {
    nbrObj++;
}

Counted::~Counted() {
    nbrObj--;
}

int Counted::getNbrObj() {
    return nbrObj;
}

void f() {
    Counted c;
    Counted* pc = new Counted;
    delete pc;
}

void g() {
    Counted c1;
    Counted c2 = c1;
}

void h() {
    Counted c1;
    Counted c2;
    c2 = c1;
}

using namespace std;

void print_nbr_objects(const string& msg) {
    cout << msg << " -- number of objects: "
         << Counted::getNbrObj() << endl;
}

int main() {
    print_nbr_objects("Program start, before f()");
    f();

    print_nbr_objects("After f(), before g()    ");
    g();

    print_nbr_objects("After g(), before h()    ");
    h();

    print_nbr_objects("After h(), program end   ");
}
Carl Rynegardh
  • 538
  • 1
  • 5
  • 22

4 Answers4

3

You've instrumented just one constructor, but C++ classes have multiple constructors. In particular, you need to instrument the copy constructor, which is one that has a signature like the following:

Counted(Counted const& other);

The copy constructor is called for at least one statement in your code:

Counted c2 = c1;
Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
2

In g() c2 is constructed with a copy constructor (which you have not implemented so it gets the default compiler generated one) but destroyed through the destructor you defined.

Rob K
  • 8,757
  • 2
  • 32
  • 36
1

In your g function, the line

Counted c1 = c1;

calls a different constructor: the copy constructor. Because this constructor doesn't increment the nbrObj, when both c1 and c2 get deconstructed they decrement the nbrObj twice.

Your g function however used the default constructor and deconstructor and so has no effect on the number.

Nonanon
  • 560
  • 3
  • 10
0

Add a copy constructor and you will get the intended results:

class Counted {
public:
    Counted();
    Counted( const Counted& other )
    {
        nbrObj++;
    }
    ~Counted();
    static int getNbrObj();
private:
    static int nbrObj;
};

int Counted::nbrObj = 0;

Counted::Counted() {
    nbrObj++;
}

Counted::~Counted() {
    nbrObj--;
}

int Counted::getNbrObj() {
    return nbrObj;
}

void f() {
    Counted c;
    Counted* pc = new Counted;
    delete pc;
}

void g() {
    Counted c1;
    Counted c2 = c1;
}

void h() {
    Counted c1;
    Counted c2;
    c2 = c1;
}

using namespace std;

void print_nbr_objects(const string& msg) {
    cout << msg << " -- number of objects: "
         << Counted::getNbrObj() << endl;
}

int main() {
    print_nbr_objects("Program start, before f()");
    f();

    print_nbr_objects("After f(), before g()    ");
    g();

    print_nbr_objects("After g(), before h()    ");
    h();

    print_nbr_objects("After h(), program end   ");
}
default
  • 2,637
  • 21
  • 44