C++——析构函数什么时候被调用

1、对象生命周期结束,被销毁时

2、delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类析构函数是虚函数时;

3、对象A是对象B的成员,B的析构函数被调用时,对象A的析构函数也被调用。

       举例来说:

class A

{

public:

      A() {ma = new int(10);}//申请一个int大小的空间,初值为10

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

      virtual ~A() { delete ma;}

      int* ma;

};

class B:public A

{

public:

      B() {mb = new[10] int();}//申请了10个int大小空间,(默认)初值均为0

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

      virtual ~B() {delete mb;}

      int* mb;

};

void DoSome()

{

     A a;

}

void mainForm()

{

      A a;                //语句一

      DoSome();     //语句二

      A* a2 = new A();      //语句三

      //doOther ...

      A* my = new B();     //语句四

}

执行语句一,结果是mainForm函数运行结束的时候,也就是a的生命周期结束才调用~A()

执行语句二,DoSome()函数体运行完成后,DoSome中a栈空间被释放前会调用~A()

执行语句三,则要等整个程序运行结束,注意不是主程序,而是整个程序。而且mainForm执行完,会造成a2指向的内存泄露,a2变成野指针(怎么解决这个问题呢?  第一种方法可以语句三后面不再使用a2之后,主动delete a2,第二种方法可以直接调用析构函数a2->~A(),第一种方法delete a2的时候会主动调用析构)

执行语句四,这个例子和语句三差不多,这里只是为了说明正确调用析构函数释放堆空间,需要结合虚函数的使用

注:理解生命周期结束的含义,比如栈对象的生命周期是从变量定义到该函数体结束,而堆对象和静态对象的生命周期是是从定义到整个程序运行结束

这里说一个容易出错的例子,比如有一个类叫做Base,有一个成员类型是自身的静态指针,如下:

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;//这里会出问题,因为delete的时候会调用自身的析构函数,析构函数里面要执行delete,而mb是静态成员,delete并不会释放掉mb开辟的空间,而是一直调用Base的析构,下一行mb=nullptr也不会执行,这样就会形成一个死循环导致栈溢出(函数递归)
    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");
}


上述代码的结果就是不断重复调用base的析构函数:~Base(),直到栈溢出。

如果把静态改为非静态,运行结果如下:

两者的区别就在mb的生命周期不同,如果是类非静态成员,执行delete则会释放申请的内存空间,然后结束。

猜你喜欢

转载自blog.csdn.net/qq_38915078/article/details/108441745