C++-when is the destructor called

1. When the object life cycle ends and is destroyed

2. When delete a pointer to an object, or delete a pointer to a base class type of the object, and its base class destructor is a virtual function;

3. Object A is a member of object B. When the destructor of B is called, the destructor of object A is also called.

       for example:

class A

{

public:

      A() {ma = new int(10);} //Apply for an int size space, the initial value is 10

      A (int sz) {ma = new int (sz);}

      virtual ~A() { delete ma;}

      int * ma;

};

class B:public A

{

public:

      B() {mb = new[10] int();} // applied for 10 int size space, (default) the initial value is 0

      B(int sz) {mb = new int(sz);}

      virtual ~B() {delete mb;}

      int * mb;

};

void DoSome()

{

     A a;

}

void mainForm()

{

      A a; //statement one

      DoSome(); //statement two

      A* a2 = new A(); //statement three

      //doOther ...

      A* my = new B(); //statement four

}

Execute statement 1, and the result is that ~A() is called when the mainForm function ends, which is the end of the life cycle of a

Execute statement two, after the body of the DoSome() function is completed, ~A() will be called before the a stack space in DoSome is released

To execute statement three, you have to wait for the end of the entire program. Note that it is not the main program, but the entire program. And the execution of mainForm will cause the memory pointed to by a2 to leak, and a2 will become a wild pointer (how to solve this problem? The first method can be used to delete a2 after statement three is no longer used, and the second method can be called directly Destructor a2->~A(), the first method will actively call destructor when delete a2)

Execute statement four, this example is similar to statement three, here is just to illustrate that the correct call of the destructor to release the heap space requires the use of virtual functions

( Note: Understand the meaning of the end of the life cycle. For example, the life cycle of a stack object is from the definition of a variable to the end of the function body, while the life cycle of a heap object and a static object is from the definition to the end of the entire program. )

 

Here is an error-prone example. For example, there is a class called Base, and a member type is its own static pointer, as follows:

class Base
{
public:

    Base()
    {
        cout << "Base() construction" << endl;
    }
    virtual ~Base();
    Base * GetInstance()
    {
        if (mb == nullptr)
        {
            mb = new Base();
        }
        return mb;
    }
    int iData;
    static Base *mb;
};

Base* Base::mb = nullptr;

Base::~Base() 
{     cout << "~Base() called" << endl;     delete mb;// There will be a problem here, because the delete will call its own destructor, which must be executed in the destructor delete, and mb is a static member, delete does not release the space created by mb, but always calls the destructor of Base, and the next line of mb=nullptr will not be executed, which will form an endless loop and cause stack overflow (function Recursion)     mb = nullptr; }



class A :public Base
{
public:
    A()
    {
        cout << "A() construction" << endl;
    }
    ~A()
    {
        cout << "~A() called" << endl;
    }
};

void Do()
{
    Base *b = new A();
    b->GetInstance();
    b->~Base();

}

void main()
{
    Do();

    system("pause");
}


The result of the above code is to repeatedly call base's destructor: ~Base() until the stack overflows.

If you change the static state to non-static state, the operation result is as follows:

The difference between the two lies in the life cycle of mb. If it is a non-static member of the class, executing delete will release the requested memory space and then end.

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_38915078/article/details/108441745