精华内容
下载资源
问答
  • 2019-09-21 12:36:46

    析构函数何时被调用

    析构函数在下边3种情况时被调用:

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

    主动调用delete ;(推荐学习:PHP编程从入门到精通)

    对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

    PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言,如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

    <?phpclass MyDestructableClass {   function __construct() {       print "In constructor\n";       $this->name = "MyDestructableClass";   }   function __destruct() {       print "Destroying " . $this->name . "\n";   }}$obj = new MyDestructableClass();?>

    和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。

    析构函数即使在使用 exit() 终止脚本运行时也会被调用。在析构函数中调用 exit() 将会中止其余关闭操作的运行。

    Note:

    析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出。脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同。

    Note:

    试图在析构函数(在脚本终止时被调用)中抛出一个异常会导致致命错误。

    转载于:https://www.cnblogs.com/68xi/p/11528033.html

    更多相关内容
  • 析构函数什么时候调用

    千次阅读 2015-06-19 14:14:20
    在这个对象的作用域最后.. 比如你在main里面声明了一个类A.....或者显式的调用析构函数 追问: 也就是说在包含该对象的函数的末尾就会调用析构函数喽? 追答: 是的.... 局部的对象 在该对象声明
    在这个对象的作用域最后..
    
    比如你在main里面声明了一个类A..那么~A()会在main结束时调用..
    如果在自定义的函数f()里面声明了一个A  函数f结束的时候就会调用~A()
    
    或者你delete 指向A的指针..
    或者显式的调用析构函数
    追问:
    也就是说在包含该对象的函数的末尾就会调用析构函数喽?
    追答:
    是的....
    
    局部的对象 在该对象声明的函数末尾被释放...
    
    你可以看下作用域的定义..析构函数就是在对象的作用域的末尾释放
    
    为了不误导人...我还是举个例子..
    
    如果是
    class A
    {
    ....
    }
    void f()
    {
       A a;
      //这种情况a的作用域就是整个函数 在f末尾释放
    }
    void f()
    {
          for(A a;a.yes();a++)//这里声明的是一个计数器a..(这种情况一般是迭代器)..
         {
                   ...
        } 
           //这里是a作用域结束的时候 调用析构函数
    }
    void f()
    {
         A* p=new A;
    
         delete p;//A作用域结束 调用析构
    }
    
    如果A是全局对象..那么就在程序末尾释放
    
    显式的调用很少见..我就不举例了..
    展开全文
  • C++——析构函数什么时候调用

    千次阅读 2020-09-07 10:25:29
    3.对象A是对象B的成员,B的析构函数调用时,对象A的析构函数也被调用。 举例来说: class A { public: A() {ma = new int(1000);} A(size sz) {ma = new int(sz);} virtual ~A() { delete ma;} in...

    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则会释放申请的内存空间,然后结束。

     

     

     

     

    展开全文
  • C++析构函数何时被调用

    千次阅读 2020-03-18 00:36:21
    一般我们都知道构造和析构的次序: 构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。...一般而言,析构函数调用顺序和构造函数的调用顺序相反,但是,对...

    一般我们都知道构造和析构的次序:

    构造从类层次的最根处开始,在每一层中,首先调用基类的构造函数,然后调用成员对象的构造函数。析构则严格按照与构造相反的次序执行,该次序是唯一的,否则编译器将无法自动执行析构过程。

    构造函数和析构函数都是由编译器隐式调用的。这些函数的调用顺序取决于程序的执行进入和离开实例化对象时所在的那个作用域的顺序。一般而言,析构函数的调用顺序和构造函数的调用顺序相反,但是,对象的存储类可以改变析构函数的调用顺序。

    • 对于在全局作用域中定义的对象,它们的构造函数是在文件中所有其他函数(包括main)开始执行之前被调用的(但无法保证不同文件的全局对象构造函数的执行顺序)。对应的析构函数是在终止main之后调用的
    • exit函数会迫使程序立即终止,而不会执行自动对象的析构函数。这个函数经常用来在检测到输入错误或者程序所处理的文件无法打开时终止程序。
    • abort函数与exit函数功能相似,但它会迫使程序立即终止,而不允许调用任何对象的析构函数。abort函数通常用来表明程序的非正常终止。
    • 自动局部变量的构造函数是在程序的执行到达定义这个对象的位置时调用的,而对应的析构函数是在程序离开这个对象的作用域时调用的(即定义这个对象的代码完成了执行)。每次执行进入和离开自动对象的作用域时,都会调用它的构造函数和析构函数。如果程序调用了exit或abort函数而终止,则不会调用自动对象的析构函数。
    • 静态局部对象的析构函数只调用一次,即执行首次到达定义这个对象的位置时。对应的析构函数是在main终止或程序调用exit函数时调用的。
    • 全局对象和静态对象是以创建它们时相反的顺序销毁的。如果程序由于调用了exit函数而终止,则不会调用静态对象的析构函数。

    析构函数在下边3种情况时被调用:

    1. 对象生命周期结束,被销毁时;
    2. delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类虚构函数是虚函数时;
    3. 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

    1、例1

    #include<iostream.h>
    class A{
         public:
             A(){
                  cout<<"constructing A"<<endl;
             }     
             ~A(){
                  cout<<"destructing A"<<endl;
             }
         private:
             int a;
    };
    class B: public A{
         public:
             B(){
                  cout<<"constructing B"<<endl;
             }
             ~B(){
                  cout<<"destructing B"<<endl;
             }
         private:
             int b;
    };
    
    void main(){
     B b;
    }
    

    运行结果为:

    constructing A
    constructing B
    destructing B
    destructing A

    上述代码还说明了一件事:析构函数的调用顺序与构造函数的调用顺序相反。

    2、例2

    例子2则正好说明了为什么基类应该把析构函数声明为虚函数,请先看下边的例子:

    #include<iostream.h>
    class A{
         public:
             A(){
              cout<<"constructing A"<<endl;
             } 
             ~A(){
              cout<<"destructing A"<<endl;
             }
        private:
             int a;
    };
    class B: public A{
         public:
             B(){
              cout<<"constructing B"<<endl;
             }
             ~B(){
              cout<<"destructing B"<<endl;
             }
         private:
             int b;
    };
    
    void main(){
         A* a = new B;
         delete a;
    }

    运行结果为:

    constructing A
    constructing B
    destructing A

    若将class A中的析构函数声明为虚函数,运行结果将变成:

    constructing A
    constructing B
    destructing B
    destructing A

    3、例3

    #include<iostream.h>
    class A{
         public:
             A(){
              cout<<"constructing A"<<endl;
             }
             ~A(){
              cout<<"destructing A"<<endl;
             }
         private:
             int a;
    };
    
    class C{
         public:
             C(){
              cout<<"constructing C"<<endl;
             }
             ~C(){
              cout<<"destructing C"<<endl;
             }
         private:
             int c;
    };
    
    class B:public A{
         public:
             B(){
              cout<<"constructing B"<<endl;
            }
             ~B(){
              cout<<"destructing B"<<endl;
            }
         private:
             int b;
             C c;
    };
    
    void main()
    {
         B b;
    }

    运行结果为:

    constructing A
    constructing C
    constructing B
    destructing B
    destructing C
    destructing A

    b的析构函数调用之后,又调用了b的成员c的析构函数,同时再次验证了析构函数的调用顺序与构造函数的调用顺序相反。

    若将上边的代码中的main()函数内容改成

     A* a = new B;
     delete a;

    由例2我们知道,这样class B的析构函数不会被调用,所以class C的析构函数也不会被调用。
    正如我们想的,运行结果为:

    constructing A
    constructing C
    constructing B
    destructing A

    原文链接:

    https://blog.csdn.net/weizhee/article/details/562833

    https://blog.csdn.net/feitianxuxue/article/details/7323054

    展开全文
  • 析构函数何时被调用

    2019-12-19 07:45:00
    B的析构函数调用之后,又调用了B的成员c的析构函数 。 若将上边的代码中的main()函数内容改成  A* a = new B;  delete a; 我们知道,这将不会调用class B的析构函数不会被调用,所以class C的析构函数...
  • 无法调用析构函数。它们是被自动调用的。 析构函数既没有修饰符,也没有参数。 例如,下面是类 Car 的析构函数的声明: class Car { ~Car() // destructor { // cleanup statements... } } 该析构函数隐式地...
  • C++中的虚析构函数到底什么时候有用的,什么作用呢。 一.虚析构函数的作用 总的来说虚析构函数是为了避免内存泄露,而且是当子类中会有指针成员变量时才会使用得到的。也就说虚析构函数使得在删除指向子类对象的基类...
  • C++析构函数调用时机

    千次阅读 2020-06-28 18:03:40
    1、在匿名对象使用完后立刻调用析构函数 2、在栈区的对象,空间被释放后立刻调用析构函数; 3、在堆区的对象,空间被delete后调用析构函数;free不能调用; 代码验证:1 void test() { MyArry(10).getLen();...
  • 在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。 简单来说,其构造函数...
  • 4、不能显式地调用析构函数,而是由系统自动调用。 定义析构函数格式为: ~类名() {…}  由于c#得到自动内存管理的支持,当对象生命期结束后,系统能够自动回收那些对象应该释放的资源等,所以一般不需要程序员...
  •  析构函数的工作方式是:底层的派生类(most derived class)的析构函数先被调用,然后调用每一个基类的析构函数。  因为在C++中,当一个派生类对象通过使用一个基类指针删除,而这个基类有一个非虚的析构函数,...
  • 在C++中,不能声明虚构造函数,但可以声明虚析构函数。多态性是指不同的对象对同一消息有不同的行为特性。虚函数作为运行时多态性的基础,主要是针对对象的,而构造函数是在对象产生之前运行的,因此虚构造函数是没有...
  • 类的析构函数调用方式堆和栈结论系统在什么情况下不会自动调用析构函数呢?举例参考 堆和栈 为了理解这个问题,我们必须首先弄明白“堆”和“栈”的概念。 堆区(heap) —— 一般由程序员分配释放, 若程序员不...
  • c++ 析构函数调用时机

    千次阅读 2017-07-09 15:03:26
    c++ 析构函数调用时机目录用 [TOC]来生成目录:c 析构函数调用时机目录 类声明如下 类定义如下 测试1 测试2 测试3 测试4 测试5 测试6析构函数在下边3种情况时被调用: 1. 对象生命周期结束被销毁时 2. delete指向...
  • 什么时候要用虚析构函数

    千次阅读 2019-04-28 16:26:19
    析构函数 在 Effective C++ 中找到了答案。书中说到在 C++ 中,当派生类(derived class)对象由一个基类(base class)指针删除时,若基类有一个非虚函数(non-virtual)的析构函数时,其结果是未定义的——实际...
  • 析构函数调用

    2021-02-10 17:07:10
    析构函数调用 多个类变量的函数共用内存,变量单独存放在不同的内存空间中,析构函数会释放这些内存空间 #include <iostream> #include <string.h> using namespace std; class person { private: ...
  • 这几天一直在模仿QQ做一个即时通讯软件,过程不是很顺利,表现...main函数中,在栈上创建的窗口,关闭的时候自动调用析构函数,这种情况不可以使用this->setAttribute(Qt::WA_DeleteOnClose);,关闭时会出现异常,如
  • 析构函数什么时候调用

    千次阅读 2014-06-18 15:49:22
    我希望c#程序在退出后自动向...然后在CLI程序一运行的时候就new A了 但是我发现程序的窗口关闭后并没有调用析构 是我用错了?还是有其他方法控制程序退出时的调用?谢谢 2012年11月22日 3:34 回复 | 引用
  • 本文给大家分享了避免析构函数调用虚函数。
  • C++析构函数的自动调用问题

    千次阅读 多人点赞 2019-04-17 10:06:09
    首先要明确一点,系统只会自动释放栈内空间,而堆内...但是,如果创建了指向new来的一块空间的指针的时候,如果在没有显示释放掉new到的堆空间时,系统是不会自动调用析构函数去释放栈空间中的指针的。 示例代码...
  • 析构函数的显示调用

    2019-02-11 00:33:09
    析构函数 今天发现析构函数居然可以显示调用,但是构造函数却不行。想到C++中STL的对象释放就是通过显示调用析构函数来释放的资源。
  • 析构函数调用时机

    千次阅读 2022-03-28 09:41:35
      当一个函数调用时候,系统会开辟一个栈帧给它,如果该函数抛出异常,那么该函数的栈帧就会被销毁,有catch语句就捕获异常进行处理,没有catch语句就继续往调用他的函数抛,像这样一直抛的过程称为栈展开。...
  • 析构函数不被调用

    千次阅读 2018-08-18 11:50:05
    写了一个测试,验证什么时候析构函数不被调用 Mycode.cpp里 #include "stdafx.h" #include "Mycode.h" Mycode::Mycode() {  ::MessageBoxW(NULL,_T("构造函数"),0,IDOK); }; My...
  • 虽然可以手动调用析构函数,但是对象的内存并没有释放。看一下代码示例: #include "stdafx.h" #include <iostream> #include <crtdbg.h> #ifdef _DEBUG #define new new(_NORMAL_BLOCK, __FILE__, _...
  • vector调用对象析构函数情况分析

    千次阅读 2020-02-25 18:37:44
    $$ 调用vector clean()函数的时候如果vector里存储的是对象则会自动调用对象的析构函数,如果存储的是指针指向的对象则不会调用对象的析构。 //clean源码部分 for ( ; first < last; ++first) //遍历元素进行析构...
  • 析构函数调用顺序

    2020-03-24 10:33:33
    如果是多个对象,调用构造函数的次序与调用析构函数的次序相反 对于不同作用域和存储类别的对象,构造函数he析构函数调用顺序 全局对象 构造函数在文件中所有函数执行前调用 当main函数执行完毕或者是调用exit...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 157,940
精华内容 63,176
关键字:

析构函数什么时候调用