Destructor being called twice when being explicitly invoked

倖福魔咒の 提交于 2019-11-27 14:37:40

It happens because you told it to happen. The destructor for an automatic variable is always called when the variable goes out of scope. You also called it. That's two calls total.

Calling an object's destructor does not signal to C++ not to call it again, since in normal execution there is no need to keep track.

The solution is to never manually call your destructor.

Calling the destructor does not free the object.

The destructor is there to clean up the internals of the object and then the object itsself is freed after the destructor finishes.

It's an error to do what you are doing similarly to the way that you can call delete twice on an object but it's an error to do so.

There are only a very few cases where you want to call the destructor manually and this isn't one of them. It's really there for the times you manually construct an object at a memory location using placement new and then need to be able to destruct it without freeing the memory.

I see that "Hello!" is being printed twice. shouldn't the calling of the destructor free the object and the destructor shouldn't be called again when it goes out of scope. Or is there some other concept ?

That's correct.

I must mention that im not intending to do this in practice. Im just trying to understand whats going on here.

You've called the destructor, preparing an object to be destroyed. But this is also done automatically when an object goes out of scope, before it's actually de-allocated.

The thing to understand is this: If you do things that don't make sense, then bad things happen. So don't do things that don't make sense. If you manually call a destructor, the descructor runs. That has no effect on anything else unless the destructor actually does something that has an effect.

You just call the destructor, you don't actually free any memory (it is statically allocated). If you use new and then delete the destructor will only be called once.

Destructor is meant to be called when an object goes out of scope if the object is in the stack as in this case or called when it is explicitly destructed with delete when the object is created on the heap with new operator at the first place.

There is no way for the compiler or the run time system to keep track whether the destructor is called by you manually or not. Also it is a very bad practice to make a call to the destructor.

If you want to do some manual cleaning (other than the object being deleted from memory or getting removed from the stack) before the object getting deleted you may do something like this.

Here you want to allow the client to manually clean things, even before the object gets deleted. But in addition to that, you clean things if client misses to clean it.

class A
{
public:
    A() : _closed(false)
    {}

    ~A()
    {
        close();
    }

    void close()
    {
        if (! _closed()) {
            // close file handles etc.
        }
    }

private:
    bool _closed
}

The destructor is not the "destroyer" of the object. It's just an ordinary function, but it's called automatically by the language immediately prior to the time of destruction.

It's official name is the destructor, but perhaps it would be more easily understood if we called it the "Before-Destruction" function.

You won't need to call to a destructor, although it is possible to do so. The compiler should implicitly run your destructor for you when an object is no longer used. When objects are created, your constructor is utilized for that object, if it has been declared with specific and initialized values for your class members. When you no longer need your object your destructor will run and delete member variable declarations and their values. This is most useful for languages that don't utilize automatic garbage collection, like C++.

SvenS

You don't call the destructor explicitly, it is called automatically when the variable goes out of scope (here after the return 0; statement). That's why it is called twice, you call it, and then the system calls it.

If you want to be able to remove an instance of this class yourself, explicitly, you need to dynamically allocate it:

temp *t = new temp;     
// do stuff with t...
delete t;    // do not forget this, or the constructor is not being called at all

You shouldn't actually call the deconstructor. It is called for you by the runtime support. Hence your calling it once and the runtime support is calling it the second time.

Here is some food for thought on destructors:

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr380.htm

You can explicitly call deconstructors, however it's not recommended, normally they are implicitly called.

The destructor of a class could be invoked:

  1. Explicitly

    When the destructor is explicitly invoked using the object of the class, the same way you invoke another member function of the class.

  2. Implicitly

    When the object of the class goes out of scope or an object which is created using the new operator is destroyed using the delete operator.

In your sample program, you do both

int main()
{
  temp t;

  t.~temp(); //1. Calling destructor explictly using the object `t`

  return 0;
} // 2. object `t` goes out of scope. So destructor invoked implictly

and that is the reason why you see the destructor being called twice.

As you have aptly thought, the destructor will destroy the resources which were created by constructor. So the destrutor should not be called explicitly, as it will result in destroying the already destroyed resource and that could be fatal.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!