精华内容
下载资源
问答
  • 2021-01-17 17:48:57

    析构函数也是一个在类中跟构造函数类似的特殊功能的成员函数,作用与构造函数相反,是在对象的声明周期结束的时候会被自动调用.在C++中析构函数的名字跟类名相同,并在前面带上一个取反的符号~,表达的意思也跟构造函数的过程相反.

    默认情况下,如果类没有定义自己的析构函数,编译器会自动为该类生成一个默认的析构函数,只不过函数体是空的,也就是什么都没做.所有,如果需要在对象被删除的时候做一些操作的话,就得自己定义析构函数.


    以下几种情况会自动调用析构函数:
    ①如果一个函数中定义了一个局部变量的对象,那么当这个函数执行结束时也就是该变量对象生命周期结束的时候,所以析构函数会被自动调用.
    ②全局变量或者static类型的变量,他们的生命周期一般是在程序退出的时候,该对象的析构函数才会被调用.
    ③如果是用new操作符动态的创建了一个对象,只有当用delete进行释放该对象的时候,析构函数才会被调用.


    析构函数的作用:
    那构造函数来说,构造函数是新建对象吗?不是,而是在对象被创建出来后自动被调用的,用来初始化相关信息的函数.同理:析构函数也不是用来删除对象的,而是当对象被删除的时候自动被调用的,用来做一些对象被删除之前的清理工作,只有对象的生命周期结束,那么程序就自动执行析构函数来完成这个工作.


    析构函数的特点:
    析构函数不返回任何值,没有函数类型,也没有任何函数的参数.析构函数不能被重载,所以,一个类中可以有多个构造函数,但只有一个析构函数.


    析构函数使用示例:

    CStudent::~CStudnet()
    {
    	cout<<"~CStudent() callec."<<endl;
    }
    

    //本文来源于VC驿站,仅作为个人学习记录

    更多相关内容
  • 详解C++中的析构函数

    2020-12-17 04:29:04
    析构函数(Destructors),是对象的成员函数,没有返回值也没有参数,且一个类只有一个析构函数,当对象被销毁的时候调用,被销毁通常这么几个情况。 函数执行结束 程序执行结束 程序块包含的局部变量 delete...
  • c++析构函数

    千次阅读 2021-01-07 18:55:14
    在main函数中创建了t0,t1,t2,t3几个对象,这里先说一下C++创建对象的三种不同方式: 1、Test p1(1); //栈中分配内存 2、Test p2 = Test(2); //栈中分配内存,跟方法1相同,是方法1的完整模式 3、Test *p3 = new ...

    c++析构函数
    首先我们来看一下有关析构函数的文字描述
    1、定义
    析构函数(destructor) 与构造函数相反,当对象结束其生命周期,如对象所在的函数已调用完毕时,系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,delete会自动调用析构函数后释放内存)。
    2、 作用:对象消亡时,自动被调用,用来释放对象占用的空间
    3、特点:
    (1) 名字与类名相同
    (2) 在前面需要加上"~"
    (3) 无参数,无返回值
    (4) 一个类最多只有一个析构函数
    (5) 不显示定义析构函数会调用缺省析构函数

    #include<iostream>
    using namespace std;
    class Test
    {
        int id;
    public:
    	Test()
    	{
    	}
        Test(int i)
        {
            id = i;
        }
        ~Test()
        {
            cout<<"ID: "<<id<<" destruction function is invoked!"<<endl;
        };
    };
    
    int main()
    {
        Test t0(0);                   //栈中分配   
    	Test t1[3]={1,1,1};           //栈中分配 
    
        Test *t2 = new Test(2);       //堆中分配
        delete t2;
    
    	Test *t3 = new Test[3]{3,3,3}; //堆中分配
        delete []t3;
        
        cout<<"------End of Main-------"<<endl;
        return 0;
    }
    

    在给出运行结果以前有必要说一下,我在vs2012的编译器里也运行了这段代码。但是其中Test *t3 = new Test[3]{3,3,3};这行代码是有错误的,我去查阅了相关的博客资料发现,在C++11中引进了这一新功能,即用new申请动态数组时可以直接初始化,形式如下:

    int* p = new int[cnt]();  //其中cnt长度和int类型都可以自己定义。
    int* p = new int[cnt]{ };
    

    而且可以用这个方式给每个成员赋值。

    int* a = new int[10] { 1,2,3,4,5,6,7,8,9,10 }; 
    

    所以说上面的Test *t3 = new Test[3]{3,3,3};语句就应该是没问题的,下面给出运行结果。
    在这里插入图片描述
    解释:
    在main函数中创建了t0,t1,t2,t3几个对象,这里先说一下C++创建对象的三种不同方式:

    1、Test t0(0;                                    //栈中分配内存
    
    2、Test t1[3]={1,1,1};          //栈中分配内存
    
    3、Test *t2 = new Test(2);     //堆中分配内存
    
    4、Test *t3 = new Test[3]{3,3,3};    //堆中分配内存
    

    方法1、2中都是在栈中分配内存,在栈中内存由系统自动的去分配和释放,而使用new创建的指针对象是在堆中分配内存,当不需要该对象时,需要我们手动的去释放(delete),否则会造成内存泄漏。

    在上述程序中,t0和t1都是栈中的对象,在程序结束时由系统来释放,因此出现在-----End of Main----之后。t2,t3是new出来的堆中对象,所以需要手动的delete释放,因此出现在最前面。另外有一点发现,就是栈中对象的释放顺序,是后定义的先释放,经过几次验证也如此,我想这恰好应征了栈的后进先出的特征。(先释放1,后释放0)

    class Test
    {
        int id;
    public:
        Test(int i)
        {
            id = i;
        }
        ~Test()
        {
            cout<<"ID: "<<id<<" destruction function is invoked!"<<endl;
        };
    };
    
    Test t0(0);                        //最先创建的对象,最后释放
    
    void Func()
    {
        static Test t1(1);               
        //创建静态对象,会在整个程序结束时自动释放
        Test t2(2);             //在Func结束时自动释放
        cout<<"-----Func-----"<<endl;
    }
    
    int main()
    {
        Test t3(3);
        t3 = 10;                         
        //类型转换构造函数,这里会创建临时对象,将int型转成Test类型对象,
        //在赋值结束后,临时变量销毁
        cout<<"------Begin of Main-------"<<endl;
        {
            Test t4(4);                 
             //花括号代表作用域,不需要等到main方法结束就释放了
        }
        Func();                          //进入Func函数
        cout<<"------End of Main-------"<<endl;
        return 0;
    }
    

    那让我们先分析一波 先是t3,t3创建完成以后想要把10赋值过来,但是一个是int类型,一个是Test,这里就会创建临时对象,将int型转成Test类型对象,在赋值结束后,临时变量销毁(把临时创建的对象得10赋值给了t3),销毁临时对象,调用一次析构函数,然后是------Begin of Main-------,到了t4,因为是在花括号里,直接调用了一次析构函数,不需要等到main方法结束,(此处如果没有花括号那么它应该在哪里呢,答案当然是在t3前面 也就是------End of Main-------之后的10前面),到了Func(); 里面的t1和t2,t1静态对象,会在整个程序结束时自动释放,t2在Func()结束时释放,所以先------Func------在调用析构函数,然后------End of Main-------,接着是释放t3,静态t1,最前面最先定义的t0;

    在这里插入图片描述

    展开全文
  • C++析构函数定义和使用

    千次阅读 2021-06-10 20:22:40
    析构函数(destructor)是一特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加一“~”符号。在C++中“~”是位“取反”运算符,从这一点可以想到:析构函数是与构造函数作用相反的函数。例如:...

    析构函数

    2.1 析构函数定义和使用

           析构函数(destructor)是一个特殊的成员函数,它的作用与构造函数相反,它的名字是类名的前面加一个“~”符号。在C++中“~”是位“取反”运算符,从这一点可以想到:析构函数是与构造函数作用相反的函数。例如:

    class student{

    public:

        student()//构造函数

        {

        }

        ~student() //析构函数

        {   }

        void print(){}

    };

           可以看到,定义了一个student类。然后,定义student类的构造函数和析构函数。其中,析构函数的定义如下:

    ~student(){ }

           那么,函数名是类名前面添加取反符号“~”,而且,函数没有参数。

           当对象的生命周期结束的时候,就会自动执行析构函数。如果出现以下几种情况,程序就会执行析构函数:

    (1) 如果在一个函数中定义了一个对象,那么,该对象就是局部对象,当这个函数被调用结束时,对象的生命周期结束。此时,对象应该释放(销毁),在对象释放(销毁)前自动执行析构函数。

    (2) static 局部对象在函数调用结束时对象并不释放(销毁),因此,不调用析构函数,只在main() 函数结束或调用exit()函数结束程序的时候,才调用static局部对象的析构函数。

    因为static局部对象的生命周期是整个程序运行过程,所以,只有程序结束运行的时候,static局部对象的生命周期才结束,才执行类的析构函数。

    (3) 如果定义了一个全局对象,全局对象的生命周期是整个程序运行过程,所以,当程序结束运行的时候,全局对象才销毁,此时,调用该全局对象的析构函数。

    (4) 如果用new运算符动态地建立了一个对象,当用delete运算符释放该对象时,先调用该对象的析构函数。

           析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前,完成一些清理工作。使这部分内存可以被程序分配给新对象使用。程序设计者要设计好析构函数,以完成所需的功能,只要对象的生命周期结束,程序就会自动执行析构函数来完成这些工作。

           析构函数不返回任何数值,也没有函数类型 和 函数参数。由于没有函数参数,因此,它不能被重载。一个类可以有多个构造函数,但是,只能有一个析构函数。

           一般情况下,类的设计者应当在声明类的同时定义析构函数,以指定如何完成“清理”的工作。如果用户没有定义析构函数,C++编译系统会自动生成一个 默认析构函数,但是,它只是有析构函数的名称和形式,实际上什么操作都不进行。想让析构函数完成任何工作,都必须在定义的析构函数中执行。

           如下是一个程序测试例子,讲解构造函数和析构函数的使用。

           程序运行结果如下:

           在main()函数中,定义一个if(1){}代码块,在代码块中定义stud局部变量。当退出代

    码块的时候,销毁stud局部变量,看到析构函数的调用。

           所以,我们看到对象销毁的时候,自动调用析构函数。析构函数是不可以手动调用的。是对象销毁的时候,由系统自动调用。

           所以,对象销毁的时候,我们想释放一些资源,就可以放在析构函数中操作。例如,student类中的name, addr是动态申请的内存。那么,在析构函数中就释放这些内存。

    韦凯峰 Linux C/C++ 程序设计教程,Linux 系统编程,Openwrt 系统开发,微信:13926572996,QQ:1523520001,博客:www.mylinux.vip

    展开全文
  • C++析构函数

    千次阅读 2019-09-23 08:45:21
    同样的,我们来看看析构函数几个特点: 函数名是在类名前加上~,无参数且无返回值。 一个类只能一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。 因为无参数无返回值...

    C++析构函数

    一、认识析构函数

    析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于撤消对象时的一些清理任务,如释放分配给对象的内存空间等。

    同样的,我们来看看析构函数的几个特点:

    • 函数名是在类名前加上~,无参数且无返回值。
    • 一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。
    • 因为无参数无返回值析构函数不能重载。每有一次构造函数的调用就会有一次析构函数的调用。
    • 当撤消对象时,编译系统会自动地调用析构函数。 如果程序员没有定义析构函数,系统将自动生成和调用一个默认析构函数,默认析构函数只能释放对象的数据成员所占用的空间,但不包括堆内存空间。
    class Data{
        public:
            Data(int year=2019,int month=9,int day=23):_year(year),_month(month),_day(day){}
            ~Data(){
        cout<<"~Data()"<<this<<endl;
    }
        private:
            int _year=1990;
            int _month;
            int _day;
    };
    void test(){
        Data test1;
    }
    int main(){
        test();
        return 0;
    }

    在test()函数中构造了对象d1,那么在出test()作用域d1应该被销毁,此时将调用析构函数,下面是程序的输出。当然在构建对象时是先调用构造函数的,在这里就不加以说明了。

    析构函数被调用的两种情况

    1)若一个对象被定义在一个函数体内,当这个函数结束时,析构函数会被自动调用。

    2)若一个对象在使用过程中运用new运算符进行动态创建,在使用delete释放时,自动调用析构函数。

    二、销毁操作

    析构函数在作用完类对象离开作用域后释放对象使用的资源,并销毁成员。

    void test(){
        int a=1;
        int b=2;
    }

    在一个函数体内定义一个变量,在test函数中定义a和b两个变量,在出了test函数后,a和b就会被销毁(栈上的操作)。如果是一个指向动态开辟的一块空间的指针(new,malloc),我们都需要进行free,否则就会内存泄露问题。

    当类类型对象的成员还有一个类类型对象,那么在析构函数里也会调用这个对象的析构函数。

    缺省的析构函数

    每个类都必须有一个析构函数。

    如果类中没有显式地为一个类定义析构函数,编译系统会自动地生成一个缺省的析构函数

    类名::析构函数命(){}

    class Date{
        public:
            Date(char *){
                str=new char[max_len];
        }
        ~Date(){ delete []str;}
        void get_info(char *);
        void send_info(char *);
        private:
            char *str;
            int max_len;
    };

    析构函数阻止该类型对象被销毁

    我们如果不想要析构函数来对对象进行释放该怎么做呢,不显式的定义显然是不行的,因为编译器会生成默认的合成析构函数。之前我们知道了如果想让系统默认生成自己的构造函数可以利用default,那么其实还有一个东西叫做delete。

    class Date{
        public:
           Date(int year=2019,int month=9,int day=1):_year(year),_month(month),_day(day){}
            ~Date()=delete;
        private:
            int _year=2019;
            int _month;
            int _day;
    };

    这么写了,又在底下创建Date类型的对象,那么这个对象将是无法被销毁的,其实编译器并不允许这么做,直接会给我们报错。

    但可以使用动态创建这个类类型对象的,像这样:Date* p = new Date;虽然这样是可行的,但当你delete p的时候依然会出错。既不能定义一个对象也不能释放动态分配的对象,所以还是不要这么用为好。

    一般在显式的定义了析构函数的情况下,应该也把拷贝构造函数和赋值操作显式的定义。

    class Date{
        public:
           Date(int year=2019,int month=9,int day=1):_year(year),_month(month),_day(day){
                p=new int;
    }
            ~Date(){
                delete p;
    }
        private:
            int _year=2019;
            int _month;
            int _day;
            int *p;
    };

    成员中有动态开辟的指针成员,在析构函数中对它进行了delete,如果不显式的定义拷贝构造函数,当你这样:Date d2(d1)来创建d2,我们都知道默认的拷贝构造函数是浅拷贝,那么这么做的结果就会是d2的成员p和d1的p是指向同一块空间的,那么调用析构函数的时候回导致用一块空间被释放两次,程序会崩溃。

     

    调用构造函数与析构函数的顺序

    1)一般顺序

    调用析构函数的次序正好与调用构造函数的次序相反,最先被调用的构造函数,其对应的构造函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。

    对象1构造函数->对象2的构造函数->对象3的构造函数->对象3的析构函数->对象2的析构函数->对象1的析构函数

    2)全局对象

    在全局范围中定义的对象(即在所有函数之外定义的对象),它的构造函数在所有函数执行之前调用。在程序流程离开其作用域时,调用该全局对象的析构函数。(包括main函数)

    3)auto局部对象

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

    4)static局部对象

    在函数中定义静态局部对象,则只在程序第一次盗用此函数建立对象时调用构造函数一次,在调用结束时对象并不释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。

    对象的生存期

    对象生存期不同分为:局部对象、全局对象、静态对象、动态对象。

    (1)局部对象

    当对象被定义时,调用构造函数,该对象被创建;当程序退出该对象所在的函数体或程序块时,调用析构函数,对象被释放。

    局部对象在被定义在一个函数体或程序块内的,它的作用域限定在函数体或程序块内,生存期比较短。

    (2)全局对象

    当程序开始运行时,调用构造函数,该对象被创建;当程序结束时,调用析构函数,该对象被释放。

    静态对象时被定义在一个文件中,它的作用域从定义是起到文件结束为止,生存期长。

    (3)静态对象

    当程序中定义静态对象时,调用构造函数,该对象被创建;当整个程序结束时,调用析构函数,对象被释放。

    全局对象是被定义在某个文件中,它的作用域包含在该文件的整个程序中,生存期最长。

    (4)动态对象

    执行new运算符调用构造函数,动态对象被创建;用delete释放对象时,调用析构函数

    动态对象由程序员掌握,它作用域与生存期是有new和delete之间的时间决定的。

     

    展开全文
  • C++ 类 析构函数

    2019-11-03 10:49:04
    C++ 类 析构函数 阅读目录 一、析构函数的定义 二、析构函数的调用 ...一类最多只能个析构函数析构函数不返回任何值,没有函数类型,也没有函数参数,因此它不被重载。 构造函数可能...
  • 如果类没有定义析构函数,那么只有类中含有成员对象(或者本类的基类)拥有析构函数的情况下,编译器才会合成一出来,否则析构函数被视为不要,也就不需要合成。例如,如下类,虽然Point类拥有虚函数:[cpp] view...
  • 析构函数的作用; 为类定义析构函数; 关于析构函数点说明; 复杂对象的构造函数和析构函数调用; 使用构造函数实现强制类型转换。
  • 浅析:类只能个析构函数

    千次阅读 2015-04-01 12:42:11
    而构造函数是可以有参数的,但是析构函数是不能有参数的。 我们知道类可以构造函数,这些构造函数是重载函数的关系,也就是说函数名都是相同的,区别它们主要靠参数的不同(参数个数和参数类型)。 但是由于...
  • C++——构造函数、析构函数以及复制构造函数

    千次阅读 多人点赞 2021-03-09 16:28:49
    文章目录一、构造函数1.1 构造函数是什么?1.2 为什么要构造函数...C++中,构造函数是一种特殊的成员函数,在每次创建一类的时候编译器都会默认调用构造函数进行初始化。 1.2 为什么要构造函数? 构造函数的作用
  • 构造函数与析构函数的问题总结

    千次阅读 2022-04-23 16:42:38
    问题四:构造函数能否声明为虚函数或者纯虚函数,析构函数呢? 问题五:构造函数、析构函数、可否声明为内联函数inline 问题六:构造函数和析构函数可以调用虚函数吗? 问题七:什么情况会自动生成默认构造函数?...
  • PHP之析构函数

    千次阅读 2018-07-19 14:55:46
    随着面向对象编程的普遍展开,面向对象展现了其中很多有趣的问题。相信很多初学者学习php面向对象时会接触两函数,构造函数与析构函数。... 析构函数常常处理的事务是一些资源释放的工作,比如前面fopen(),...
  • 析构函数为虚函数

    千次阅读 2019-06-20 12:37:14
    多态是面向对象的一基本属性,包括静态多态(编译阶段)和动态多态(运行阶段),静态多态主要是指函数参数不同产生的多态性,是在编译阶段可以识别的一种多态机制,而运行时多态则主要用于基类指针指向派生类对象...
  • 我是柠檬叶子C,本章将继续讲解C++中的面向对象的知识点,本篇主要讲解默认成员函数中的构造函数、析构函数和拷贝构造函数。还是和以前一样,我们将由浅入深地去讲解,以 "初学者" 的角度去探索式地学习。会一步步地...
  • c++中的析构函数

    万次阅读 多人点赞 2019-04-09 20:55:46
    印象中c++的析构函数是会自动调用。但是今天运行程序的时候,却没有进入到我写的析构函数,让我不禁怀疑,最终到底析构了没有。还是暗自调用了系统的析构。所以来记载一下析构的知识。 以下属转载,原文博客地址:...
  • 析构函数三. 拷贝构造函数1.浅拷贝2.深拷贝四. 赋值函数 在C++中,对于一类,C++的编译器都会为这类提供四默认函数,分别是: A() //默认构造函数 ~A() //默认析构函数 A(const A&) //默认拷贝构造...
  • 析构函数 拷贝构造函数 运算符重载 class Date { }; 可以看到,上面那个类没有任何成员,是一空类,但是它真的什么都没有吗?其实一类在我们不写的情况下,都会生成6默认的成员函数 分别是构造函数,析构...
  • 4. 构造函数与析构函数)【C++】
  • 目录 0. 整体概述为什么要引入构造函数 1. 声明和定义构造函数 程序声明对象时,将自动调用构造函数 1.1 成员名和参数名 ...什么时候调用析构函数呢? 5 改进Stock类 stock10.h Stock10.cpp ...
  • 类中6默认函数,如果在定义类时没有定义这6... 析构函数 拷贝构造函数 赋值运算符重载函数 取地址操作符重载函数 const修饰的取地址操作符重载函数   构造函数  1.构造函数与类名相同,并且没有返回值  2...
  • 这些天在看C++的过程中一直搞不太懂构造函数和析构函数的调用顺序,特别是析构函数,不带参数不好进行测试,这里把这天遇到的问题写了代码跑了一下,和大家分享一下,写的不对的地方,欢迎大家批评指正。...
  • 多态是面向对象的一基本属性,包括静态多态(编译阶段)和动态多态(运行阶段),静态多态主要是指函数参数不同产生的多态性,是在编译阶段可以识别的一种多态机制,而运行时多态则主要用于基类指针指向派生类对象...
  •     每个类都分别定义了它的对象被初始化的方式, 类通过一个或几个特殊的成员函数来控制器对象的初始化过程, 这些函数叫做构造函数。     构造函数的任务是初始化对象的数据成员, 无论何时只要类的对象...
  • 导言 对象是由“底层向上”开始构造的,当建立一对象时,首先调用基类的构造函数,然后调用下一派生...1.构造函数能有返回值 2.缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数
  • 指针只是指向了一个内存地址,但是当存内存中取值的时候,系统不知道你要从当前指针指向的地址,取几个字节,指定了指针的类型后,系统就知道取几个字节了。 char类型取1个字节,short类型取2个字节,int类型去4个...
  • c++中构造函数及析构函数特性

    千次阅读 2017-10-02 18:10:27
    3、c++规定,如果一类没有提供任何的构造函数,那么c++编译器会提供一默认的构造函数,且这默认的构造函数是不带参数的构造函数,它只负责对象的创建,不进行对象的初始化。 4、只要一类定义了一构造...
  • C++析构函数释放对象的空间顺序。

    千次阅读 2019-01-14 16:13:58
    一、定义 1. 作用:对象消亡时,自动被调用,用来释放... (4) 一类最多只有一个析构函数  (5) 不显示定义析构函数会调用缺省析构函数 二、用法 1.普通用法 代码: class Test { int id; public: Test...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 47,305
精华内容 18,922
关键字:

析构函数能有几个参数