精华内容
下载资源
问答
  • php析构函数调用class a{function construct(){echo "start to construct a objn";}function pide($a,$b){//exit(1);//destruct calledreturn $a/$b; //destruct called when $b=0;}function add($a,$b){throw new ...

    php析构函数调用

    class a{

    function construct(){

    echo "start to construct a objn";

    }

    function pide($a,$b)

    {

    //exit(1);//destruct called

    return $a/$b; //destruct called when $b=0;

    }

    function add($a,$b)

    {

    throw new Exception ("daone");//destruct called

    return $a+$b;

    }

    function destruct(){

    echo "start to destructn";

    }

    }

    try{

    $first = new a();

    //$r = $first->pide(4,0);

    $first->add(4,0);

    }

    catch(Exception $e)

    {

    echo "cath exception n";

    }

    从上面的例子可以看出,php抛出异常(不管外面有没有try catch),直接退出的情况下,都会调用析构函数。

    展开全文
  • 虽然我们没有显示地调用析构函数,但是编译器都会默认地为我们执行析构函数。 那么当我们执行 BaseClass *base = new BaseClass(); 当我们执行 delete base时,会调用析构函数为我们释放资源。而 我们执行Base...

    综合解答https://www.cnblogs.com/lpxblog/p/5890933.html

    基类的析构函数为什么必须是虚函数呢?

    • 我们都知道,想要回收一个对象申请的资源,那么就需要调用析构函数。虽然我们没有显示地调用析构函数,但是编译器都会默认地为我们执行析构函数。

    • 那么当我们执行 BaseClass *base = new BaseClass(); 当我们执行 delete base时,会调用析构函数为我们释放资源。而 我们执行BaseClass *sub = new SubClass(); 如果BaseClass基类的析构函数不是虚函数的时候,delete sub 对象的时候,只会释放BaseClass 基类申请的资源,而不是释放SubClass派生类的资源。原因如下:

    • 基类指针指向了派生类对象,而基类中的析构函数是非virtual的,而虚构函数是动态绑定的基础。现在析构函数不是virtual的,因此不会发生动态绑定,而是静态绑定,指针的静态类型为基类指针,因此在delete的时候只会调用基类的析构函数,而不会调用派生类的析构函数。这样,在派生类中申请的资源就不会得到释放,就会造成内存泄漏,这是相当危险的:如果系统中有大量的派生类对象被这样创建和销毁,就会有内存不断的泄漏,久而久之,系统就会因为缺少内存而崩溃。

    • 当然,如果在派生类中没有动态申请有资源的时候,是不会造成内存泄漏的。而当派生类对象的析构函数中有内存需要回收,并且在编程过程中采用了基类指针指向派生类对象,如为了实现多态,并且通过基类指针将对象销毁,这时,就会因为基类的析构函数为非虚函数而不触发动态绑定,从而没有调用派生类的析构函数而导致内存泄漏。

    • 因此,为了防止这种情况下的内存泄漏的发生,最后将基类的析构函数写成virtual虚析构函数。

    C++的构造函数为何不能为虚函数

    1. 存储空间角度:虚函数对应一个vtable,vtable存储于对象的内存空间
      若构造函数是虚的,则需要通过 vtable来调用,若对象还未实例化,即内存空间还没有,无法找到vtable

    2. 使用角度:虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。
      构造函数本身就是要初始化实例,那使用虚函数就没有实际意义

    3. 从实际含义上看,在调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有太大的必要成为虚函数

    构造函数或者析构函数中调用虚函数会怎样https://www.cnblogs.com/vincently/p/4754206.html
    构造函数中调用虚函数单补解析https://blog.csdn.net/magictong/article/details/6734241

    展开全文
  • 析构函数

    2020-03-26 17:01:35
    一.作用 用于完成对象被删除前的...如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数 规定: 1.是类的公有函数成员,名称由类名前加” ~”构成 2.没有参数,没有返回值 3.一个类中只能定义一个析构...

    一.作用

    用于完成对象被删除前的一些清理工作。至于完成怎样的清理工
    作,由设计者在函数体中实现。

    二.调用时间

    在对象的生存期结束的时刻,即在删除一个对象前由系统自动调用,然
    后再释放此对象所属的空间。

    三.默认的析构函数

    如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数
    规定:
    1.是类的公有函数成员,名称由类名前加” ~”构成
    2.没有参数,没有返回值
    3.一个类中只能定义一个析构函数,不能重载
    4.形式: 类名::~类名(){}
    5.一般情况下,可以不定义析构函数
    但如果类的数据成员中包含指针变量是从堆上进行存储空间
    分配的话,需要在析构函数中进行存储空间的回收

    四.编写一个代码检验析构函数是否执行

    #include <iostream>
    #include <cstring>
    using namespace std;
    class Test
    {
    private:
    int a;
    char *str;
    public:
    Test(int b, char *s) //构造函数
    { a=b; str=new char[strlen(s)+1]; strcpy(str,s); }
    void setA(int b) {a=b; }
    void setStr(char *s) { strcpy(str,s); }
    void show () {cout<<a<<","<<str<<endl; }
    Test(const Test& C) {
    a=C.a; str=new char[strlen(C.str)+1];
    strcpy(str,C.str); }
    ~Test(){delete str; cout<<“析构函数”<<endl; } //析构函数//类的数据成员中包含指针变量str是从堆上进行存储空间分配,需要在析构函数中进行存储空间的回收。
    };
    int main()
    {
    Test xx(100,"hello");
    Test yy(xx);
    xx.show(); yy.show();
    xx.setA(80); xx.setStr("abc");
    xx.show(); yy.show();
    return 0;
    }
    

    运行结果

    100,hello
    100,hello
    80,abc
    100, hello
    析构函数
    析构函数
    

    五.构造函数和析构函数举例

    注意
    数据成员是字符串时,可以用分别使用:字符数组,string类的对象,字符指针表示字符串。处理方法略有不同。

    #include <iostream>
    #include <string>
    using namespace std;
    class CStudent
    {private:
    int number;
    char name[20]; //字符数组
    string addr; //string类的对象
    char *email; //字符指针
    int age;
    public:
    CStudent(int xh=0, char *xm="Noname", string ad="Noad",char *em="Noemail",int a=18);
    CStudent(const CStudent & s); //复制构造函数
    ~CStudent( ); //析构函数
    void setStudent(int xh=0, char *xm="Noname", string ad="Noad",char *em="Noemail",int a=18);
    void printStudent( );
    int GetAge( );
    };
    CStudent::CStudent(int xh, char *xm, string ad,char *em,int a)
    { number = xh;
    strcpy(name, xm); //字符数组
    addr=ad; //string类的对象
    email=new char[strlen(em)+1];strcpy(email, em); //字符指针
    age = a; 
    }
    CStudent::CStudent(const CStudent & s)
    { if(this!=&s){
    number = s.number;
    strcpy(name, s.name); //字符数组
    addr=s.addr; //string类的对象
    email=new char[strlen(s.email)+1];strcpy(email, s.email);
    //字符指针
    age = s.age; 
    } }
    void CStudent::setStudent(int xh, char *xm, string ad,char *em, int a)
    { number = xh;
    strcpy(name, xm); //字符数组
    addr=ad; //string类的对象
    delete []email; //字符指针
    email=new char[strlen(em)+1];strcpy(email, em);
    age = a; }
    CStudent::~CStudent( ){
    delete [ ]email; //字符指针
    //cout<<number<<endl; }
    void CStudent::printStudent(){
    cout<<number<<" "<<name<<" "<<addr<<" "<<email<<" "<<age<<endl;}
    int CStudent::GetAge()
    { return age;}
    int main()
    {
    int sum=0;
    CStudent s[8] = { CStudent(10000, "AAAAAA", "shanghai", "aaa@126.com", 20),
    CStudent(10001, "BBBBBB", "qinghai", "bbb@126.com",22 ),
    CStudent( ),CStudent( ),
    CStudent(10004, "EEEEEE", "shangdang", "eee@126.com",18 )
    };
    s[2].setStudent(10002, "CCCCCC", "weihai", "ccc@126.com",24 );
    s[3].setStudent(10003, "DDDDDD", "shandong", "ccc@126.com",21 );
    s[5].setStudent(10005, "FFFFFFF", "heihai", "fff@126.com",23 );
    s[6].setStudent(10006, "GGGGG", "shanxi", "ggg@126.com",20 );
    s[7].setStudent(10007, "HHHHH", "jiangsu", "hhhh@126.com",20 );
    for(int i=0; i<8; i++)
    { sum += s[i].GetAge();
    s[i].printStudent(); }
    cout << sum/8 << endl;
    return 0;
    }
    

    六.调用构造函数和析构函数的顺序

    1.一般情况下,对同一存储类别的对象,调用析构函数的次序和调用构造函数的次序相反.
    2.对于不同作用域和存储类别的对象构造函数和析构函数的调用顺序

    • 全局对象

      • 构造函数在文件中所有函数执行前调用;
      • 当main函数执行完毕或调用exit函数时(此时程序终止) ,调用析构函数。
    • 函数中定义的自动局部对象(例如在函数中定义对象) :

      • 在建立对象时调用其构造函数,如果函数被多次调用,则在每次建立对象时都要调用构造函数
      • 在函数调用结束、对象释放时先调用析构函数
    • 函数中定义的静态(static )局部对象:

      • 第一次调用此函数建立对象时调用构造函数一次
      • 在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数
    #include <iostream>
    #include <string>
    using namespace std;
    class Test
    {
    private:
    int a;
    char *str;
    public:
    Test(int b, char *s) //构造函数
    { a=b; str=new char[strlen(s)+1]; strcpy(str,s); 
    cout<<str<<" 构造函数"<<endl; }
    void setA(int b) { a=b; }
    void setStr(char *s) { strcpy(str,s); }
    int getA( ) {return a; }
    void show ( ) {cout<<a<<","<<str<<endl; }
    Test(const Test& C) { //复制构造函数
    a=C.a; str=new char[strlen(C.str)+1];
    strcpy (str,C.str); }
    ~Test( ){ cout<<str<<" 析构函数"<<endl; delete str; } //析构函数
    };
    Test a(100,"hello"); //全局对象
    void f(char xx[]){ //外部函数
    cout<<"function f:"<<endl;
    Test x(90,xx); //函数中定义的自动局部对象
    static Test y(0,"static"); //函数中定义的静态(static )局部对象
    x.show( ); y.show( );
    y.setA(y.getA( )+10);
    }
    int main()
    {
    Test b(a);
    a.show( ); b.show( );
    b.setA(80); b.setStr("abc");
    a.show( ); b.show( );
    f("111");f("222");f("333");
    return 0}
    

    运行结果

    hello 构造函数
    100,hello
    100,hello
    100,hello
    80,abc
    function f:
    111 构造函数
    static 构造函数
    90,111
    0,static
    111 析构函数
    function f:
    222 构造函数
    90,222
    10,static
    222 析构函数
    function f:
    333 构造函数
    90,333
    20,static
    333 析构函数
    abc 析构函数
    static 析构函数
    hello 析构函数
    
    展开全文
  • 全局构造/析构函数与C/C++运行库主要以MSVC CRT来说:大致的过程如下:mainCRTStartup(){ ... _initterm(__xc_a, __xc_z);}typedef void (__cdecl * _PVFV)();static void __cdecl _initterm(_PVFV* pfbegin, _PVFV* ...

    全局构造/析构函数与C/C++运行库

    主要以MSVC CRT来说:

    大致的过程如下:


    __xc_a, __xc_z分别处于两个特殊的段里, 并具有long,read属性.
    因此这两条pragma指令实际在obj文件里生成了名为.CRT$XCA和.CRT$XCAZ的两个段.
    __declspec(allocate(x))将其分别分配到对应段中

    当链接的时候,链接器会将所有相同属性的段合并,注意的是,合并到输出段时,是根据字符表顺序依次排序.
    由于.CRT$XC*这些段的属性都是只读的,且名字很相近,最后往往被放到只读段中,成为.rdata的一部分.
    这样就形成了存储所有全局初始化函数的地址的数组.

    还有:.CRT$XC*段中存放的是该obj文件的全局初始化函数的地址.所以最后形成的是一个函数地址数组.

     

    结果: Hello world!

     

    MSVC CRT 析构

    是当调用初始化函数的时候,用atexit函数注册了析构函数的执行地址.

     

    展开全文
  • 析构函数(自动调用) 对象***生存期结束时***,需要做清理工作,比如:释放成员(指针)所占有的存储空间。析构函数可以完成上述工作。  作用:用于完成对象被删除前的一些清理工作。至于完成怎样的清理工 作,由...
  • 构造函数,析构函数

    2012-05-14 17:31:02
    子类生成对象时 是先调用父类的构造函数调用自己的构造函数 析构时的顺序是怎样的? 比如下面 #include using namespace std; class A{ public:  A(){cout  virtual void p(){cout  ~A(){cout }...
  • C++基础--构造函数与析构函数在C++中,有两种特殊的成员函数,即是构造函数和析构函数,下面分别予以介绍。10.2.1 构造函数 变量应该被初始化,我们已经知道了简单变量的初始化、数组的初始化、结构和结构数组的...
  • 例如,新生被录取人大学,在人学报到时,先有一名工作人员审查材料,他的职责是甄别资格,然后根据录取通知书上注明的录取的系和专业,将材料转到有关的系和专业,办理具体的注册人学手续,也可以看作调用不同部门的...
  • 所学回顾1.1 C++的析构函数为什么要设成虚函数1.2 栈中存放什么1.3 未初始化的静态变量存在哪里1.4 螺旋数组1.5 string类的实现2. 明日(5月13日)目标 0. 目标完成情况 unp第2章和第3章看完 ---------- 两天了还是...
  • 编写的每个类几乎都有一个或多个构造函数、一个析构函数和一个赋值运算符。这些是编写一个类所必需的一些函数,控制着类的基本操作,如产生对象并初始化,以及从系统中排除旧对象并对其进行恰当的清理工作,还有赋予...
  • 如题,类似于这样的函数,在一个函数之中定义了一个对象...}探究对象生命周期当然要去看何时调用析构函数,下面贴出完整代码:#include &lt;iostream&gt;using namespace std;class Teacher{private: char...
  • 定义学生类,并在主函数定义类的对象进行调用测试。 要求: ① 数据成员 ② 具有无参和有参的构造函数。 ③ 具有深... ④ 具有析构函数。 ⑤ 具有输出函数、排序函数等。
  • C++编译器合成的默认函数(第二篇)

    千次阅读 多人点赞 2018-12-02 18:59:46
    概述 前面我们整理了编译器合成的默认构造函数,也进行了深度的解析,那其他...对于未定义析构函数的类,编译器会默认生成一个非虚析构函数,该析构函数调用成员以及基类的析构函数。 如果在类中申请了动态资源...
  • 在main()函数执行后,程序退出,这时候会对全局变量和全局对象进行销毁操作,所以还会执行析构函数的代码。 2. atexit 函数 使用atexit函数,注册一个或多个函数,它们被注册在栈中, 在 main 函数结束后被调用,...
  • 问题一 : 析构函数的顺序和构造函数的顺序有什么关系 答:析构函数的顺序和构造函数的顺序相反 问题二: 单个对象创建时构造函数的调用顺序是怎样的 答:1.。先调用父类的构造过程(调用父类的构造函数) 2。...
  • 构造函数

    2016-06-03 14:25:40
    5 析构函数 */ //定义一个类只需要用class关键字后跟类的名称即可 ,类的名称通常每个单词的第一个字母大写,以大括号开始结束。 class NbaPlayer{ public $name="Jodan"; public $weight="98kg"; publi
  • 在C++中,不仅C++的关键字new和delete可以分配和释放堆空间,而且可以通过建立new建立的对象要调用构造函数,通过delete删除对象也要调用析构函数。 下面,来比较下面的同一个函数的C和C++描述: void fn...
  • C++高频知识总结P4

    2020-09-03 15:34:49
    2.构造函数或者析构函数调用虚函数会怎样?3.声明和定义的区别?4.指针函数和函数指针?5.指针常量?常量指针?6.深拷贝与浅拷贝7.什么时候需要自定义拷贝构造函数?8.右值引用? C++ 1.构造函数可以是虚函数吗?...
  • 当一个shared_ptr对象超出作用域时,其析构函数调用,在析构函数中,将其引用计数减1,如果引用计数的值变为0,则删除关联的原始指针。 要删除析构函数中的内部原始指针,默认情况下,shared_ptr调用delete()函数...
  • 如果有人拿这段话来总结...new/delete会调用operator new/delete 来开辟/释放内存,也会调用构造/析构函数来初始化/释放资源。 当然还有一句无聊的:由于malloc/free看不到构造/析构函数,所以不要混用new/delete,...
  • C++ Primer Plus学习笔记之继承类的初始化顺序 基类的构造函数,析构函数和操作符函数operator=是不能被派生类继承的;...另一方面,执行析构函数时,先执行派生类的析构函数,再执行基类的析构函数。原因是,对
  • C++ 中继承与动态内存分配的详解 继承是怎样与动态内存分配进行互动的呢?...实际上,派生类的默认构造函数总是要执行一些操作:执行自身的代码后调用基类析构函数。因为我们假设派生类的成员不需要执行任何特
  • 同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误...
  • 同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误...
  • 同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译错误...
  • 同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译...
  • 同样,子类的析构函数也会自动调用父类的析构函数。要想一个类不能被继承,我们只要把它的构造函数和析构函数都定义为私有函数。那么当一个类试图从它那继承的时候,必然会由于试图调用构造函数、析构函数而导致编译...

空空如也

空空如也

1 2 3 4 5
收藏数 95
精华内容 38
关键字:

怎样调用析构函数