精华内容
下载资源
问答
  • C++ 析构函数
    千次阅读
    2021-01-25 17:21:15

    1、析构函数

    析构函数,其实就是构造函数的相反操作,构造函数是创建对象时候,用来给对象的成员数据赋值的,而析构函数是用了清理对象的。


    2、析构函数的特点

    ①析构函数就是位取反运算符+类名表示。

    ②构造函数可以有多个,而析构函数只能有一个,不可重载,不能有参数。

    ③与构造函数相同,析构函数没有返回值。如果没有显式写出析构函数,编译器会自动加上一个默认的析构函数,如果写了的话,就不会再加。

    #include<bits/stdc++.h>
    using namespace std;
    class Point{
        public:
            Point(double xx=0.0,double yy=0.0);
            ~Point();
            void get();
        private:
            double x,y;
    };
    Point::Point(double xx,double yy):x(xx),y(yy){
    }
    Point::~Point(){
        cout<<"end"<<endl;
    }
    void Point::get(){
        cout<<"x="<<x<<"  y="<<y<<endl;
    }
    int main(){
        Point a(5.0,6.0);
        a.get();
        return 0;
    }
    

    3、析构函数被调用的情况

    ①对象的生命周期结束。(比如在函数中的声明 函数结束前会调用)

    void fun(){
        Point a(5.0,6.0);
    }
    int main(){
        fun();
        return 0;
    }
    

    ②如果对象是new出来的,用delete释放空间时候会调用。不手动delete是不会调用析构函数的。

    int main(){
        Point *a=new Point(6.0,7.0);
        delete a;
        return 0;
    }
    

    ③对象a是对象b的成员,对象b的析构函数被调用时候,对象a的析构函数也会被调用。

    #include<bits/stdc++.h>
    using namespace std;
    class Point{
        public:
            Point(double xx=0.0,double yy=0.0);
            ~Point();
            void get();
        private:
            double x,y;
    };
    Point::Point(double xx,double yy):x(xx),y(yy){
    }
    Point::~Point(){
        cout<<"Point end"<<endl;
    }
    void Point::get(){
        cout<<"x="<<x<<"  y="<<y<<endl;
    }
    
    class Line{
        public:
            Line();
            ~Line();
        private:
            Point point;
    };
    Line::Line(){
    }
    Line::~Line(){
        cout<<"Line end"<<endl;
    }
    
    class test{
        public:
            test();
            ~test();
        private:
            Line line;
    };
    test::test(){
    }
    test::~test(){
        cout<<"test end"<<endl;
    }
    int main(){
        test A;
        return 0;
    }
    

    4、总结

    析构函数不仅仅是用来清理对象释放内存的,也可以是在析构函数中编写在清理对象前需要做的一些工作。

    更多相关内容
  • 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++析构函数

    2019-09-23 08:45:21
    C++析构函数 一、认识析构函数 析构函数也是一种特殊的成员函数。它执行与构造函数相反的操作,通常用于撤消对象时的一些清理任务,如释放分配给对象的内存空间等。 同样的,我们来看看析构函数的几个特点: 函数...

    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++ 析构函数与变量的生存周期实例详解 这篇介绍了析构函数,是我的读书笔记,我希望它够简短但又比较全面,起到复习的作用。如果有一些C++知识记不清楚了,它可以帮你很快回忆起来。 析构函数(destructor)的名字...
  • 主要介绍了C++中虚析构函数的作用及其原理分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • C++析构函数定义和使用

    千次阅读 2021-06-10 20:22:40
    C++中“~”是位“取反”运算符,从这一点可以想到:析构函数是与构造函数作用相反的函数。例如: class student{ public: student()//构造函数 { } ~student() //析构函数 { } void print(){} };...

    析构函数

    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++时,看到书上有建议析构函数函数设置为虚函数,一直不理解,现在我们写代码验证下这一建议。 先看下不带virtual 的析构函数 using namespace std; class TBase { public: TBase() {} ~TBase() { cout &...
  • 详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数  编写类String 的构造函数、析构函数和赋值函数,已知类String 的原型为: class String { public: String(const char *str = NULL); // 普通...
  • C++析构函数和delete关系

    千次阅读 2020-10-23 16:41:16
    在栈上的对象,作用域结束后自动调用析构函数(自动的),而delete用于在堆上创建的空间,执行delete后,程序会执行该对象的析构函数,而不执行delete程序不会自动执行析构函数(也就是说,不使用delete它就不析构)...
  • 这篇文章用于总结当析构函数是普通析构函数、虚析构函数、纯虚析构函数时,我们使用delete运算符删除一个指针对象时,析构函数会有什么情况发生;普通析构函数CBase是基类,CDerive是其子类,类源码代码如下:class ...
  • C++析构函数调用时机

    2020-06-28 18:03:40
    1、在匿名对象使用完后立刻调用析构函数 2、在栈区的对象,空间被释放后立刻调用析构函数; 3、在堆区的对象,空间被delete后调用析构函数;free不能调用; 代码验证:1 void test() { MyArry(10).getLen();...
  • 主要介绍了详解C++中如何将构造函数或析构函数的访问权限定为private的方法,文中还解释了构造函数与虚函数的区别,需要的朋友可以参考下
  • C++析构函数何时被调用

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

    千次阅读 2020-08-06 09:55:15
    = nullptr){ delete one } } int main() { One one // 这样是不行的,不能访问析构函数 One *one //ok One *one = new One() //ok return 0; } 析构函数一般不设置成私有。如果析构函数设置成私有,不能在栈上创建...
  • 如何使用C++析构函数

    千次阅读 2020-02-18 14:56:10
    析构函数 析构函数通常用于释放在构造函数或在对象生命期内获取的资源(如动态分配的内存) 。 析构函数的作用并不仅限于释放资源方面, 它可以包含任意操作, 用来执行“对象即将被撤销之前程序员所期待的任何...
  • 深度剖析C++析构函数

    千次阅读 2017-12-09 21:48:36
    由于析构函数往往还设置成虚函数,所以这里我重点介绍下C析构函数的原理和各种场景。 一、析构函数的作用 当对象的生命周期结束时,会自动调用析构函数,以清理一些资源,比如释放内存、关闭文件、关闭数据库连接...
  • C++析构函数何时需要自定义?

    千次阅读 2020-06-02 16:12:27
      析构函数:如果我们自己不写,编译器会帮我们写(编译器自己写的析构里面什么都不干)。什么时候必须要我们自己写?如果本类中一个成员变量是别的对象的指针,而且这个指针不是...C++何时需要自定义析构函数呢? ...
  • C++析构函数只声明而不定义的问题

    千次阅读 2020-11-19 17:44:41
    C++析构函数只声明而不定义的问题 现附上一个简单的小例子(计算圆柱体体积) #include<iostream> using namespace std; //计算圆柱体体积 class cylinder//圆柱体 { public: double r; double h; ...
  • C++析构函数的简单范例

    千次阅读 2018-02-25 20:31:23
    问题:C++析构函数的简单范例 本程序通过VC++ 6.0编译与测试,具体代码如下: #include &lt;iostream&gt; using namespace std; class Destructor { public: Destructor(); //构造函数 ~Destructor(); ...
  • c++析构函数没有执行

    千次阅读 2019-09-20 00:20:32
    如果发现自己的析构函数没有被调用,有可能是因为在delete的那个地方,没有#include相应的头文件,而只是用了class的前置声明。如下: class AAA; //这里只有前置声明AAA,并没有include它的头文件 void ...
  • C++ 析构函数(函数前面有波浪号~)

    千次阅读 2021-08-09 15:55:53
    什么是析构函数 析构函数定义类型和构造函数的定义类型差不多,也是名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭...
  • C++ 析构函数的特点

    2019-09-05 19:32:33
    析构函数的特点包括: 没有参数 自动调用 没有返回值 不能被重载
  • C++析构函数的自动调用问题

    千次阅读 多人点赞 2019-04-17 10:06:09
    当单纯的创建对象的时候,对象存放在栈中,此时在程序块的}后面,系统会自动调用析构函数,释放掉栈空间。 但是,如果创建了指向new来的一块空间的指针的时候,如果在没有显示释放掉new到的堆空间时,系统是不会...
  • 资源来源于老师的参考答案,里面含有线性表实现的参考程序,可以帮助初学者了解基本的c++中的析构函数

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 141,154
精华内容 56,461
关键字:

c++ 析构函数

c++ 订阅
友情链接: wxllong.rar