Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ stack based constructor/destructor not working as expected

Tags:

c++

I have trouble understanding why the following code doesn't construct and destruct the two objects I create the way I'd expect:

#include <iostream>

class MyClass {

    int myVar;

public:
    MyClass(int x) {
        myVar = x;
        std::cout << "constructing " << myVar << ", " << (long)this << std::endl;
    }

    ~MyClass() {
        std::cout << "destructing " << myVar << ", " << (long)this << std::endl;
    }
};

int main(int argc, const char * argv[])
{
    MyClass a = MyClass(1);
    a = MyClass(2);
    return 0;
}

I'd think that inside main I first create an object with the value 1, then create a new one with value 2. And each of the objects gets constructed and destructed, so that I'd expect to see the following output:

constructing 1, 3456
constructing 2, 6789
destructing 1, 3456
destructing 2, 6789

However, I get this:

constructing 1, 3456
constructing 2, 6789
destructing 2, 6789   <- note the "2"
destructing 2, 3456

Update: I've added output of the object's address (this) so that one can better see which object does what.

When I use "new MyClass" instead, I do not run into this weird effect.

What is causing this, and, understanding my goal, what is the right way to avoid similar mistakes in the future?

While this example looks harmless, I ran into crashes of my code because I had allocated other objects in the constructor and freed them in the destructor. This did lead to freeing the objects when the object was still in use.

Conclusion

Now that all my questions are answered, let me summarize:

  1. In the above example I'm using "myVar", which doesn't show even the issue that caused me to bring up this question. My apologies for that.
  2. The actual issue I had with the code is that I was not using a simple int var but an array that I created with "new" in the destructor, and freed with delete in the destructor. And with that, the array would get deleted twice, leading to incorrect data in my program.
  3. The fix is to not use a simple pointer to the array but a reference counting pointer, so that, when it gets copied by the assignment operator, it increases the refcount, thereby preventing premature release of it.
  4. In general, the effect I've shown here is nothing dangerous - it doesn't damage anything as I had gotten the impression. The dangerous part was that I didn't use ref counting ptrs.
like image 518
Thomas Tempelmann Avatar asked Nov 28 '22 08:11

Thomas Tempelmann


1 Answers

The line a = MyClass(2); will not call a destructor, it will call the assignment operator (MyClass::operator=) which you have not implemented, so the compiler provides one for you - it doesn't "print" anything, so you don't see that.

The reason you get destrucing 2 twice is that immediately after the line a = MyClass(2);, the temporary MyClass(2) object is destroyed. Then at the end of main the variable a is destroyed, and since myVar is now 2, it prints 2 again.

like image 57
Mats Petersson Avatar answered Dec 10 '22 12:12

Mats Petersson