• C++对析构函数的误解(转)


    C++析构前言

    析构函数在什么时候会自动被调用,在什么时候需要手动来调用,真不好意思说偶学过C++…今日特此拨乱反正

    C++析构误解正文

    对象在构造的时候系统会分配内存资源,对一些数据成员进行初始化或者赋值;一个良好的class需要有资源回收的机制,而这一操作便落在了析构函数的头上,析构函数来负责类内的资源的free。来看一段代码:

    class myclass
    {
        public:
            myclass()
            {
                cout << "构造函数" <<endl;
            }
            ~myclass()
            {
                cout << "析构函数" <<endl;
            }
    };
    
    int main()
    {
        myclass mc;
        return 0;
    }

    执行结果:

    图1

    在main主函数当中,如果直接声明一个对象,在声明的时候,直接就调用了类内的构造函数,在主函数结束之前的那一小刻,也自动调用了这个类的析构函数;在看一段代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using  namespace std;
    
    class myclass
    {
        public:
            myclass()
            {
                cout << "构造函数" <<endl;
            }
            ~myclass()
            {
                cout << "析构函数" <<endl;
            }
    };
    
    int main()
    {
        myclass *mc;
        return 0;
    }

     执行结果:

    在main主函数当中,如果直接声明一个对象指针(只是声明而已),既不自动调用构造函数和析构函数。但是将main函数改为下面:

    class myclass
    {
        public:
            myclass()
            {
                cout << "构造函数" <<endl;
            }
            ~myclass()
            {
                cout << "析构函数" <<endl;
            }
    };
    
    int main()
    {
        myclass *mc;
        mc =new myclass();
        return 0;
    }

    执行结果:

    这里不仅声明了一个对象指针,而且new了,这说明给这一对象指针分配一个内存空间,当然这就会调用构造函数了;咦,奇怪了,为什么不自动调用析构函数了,说明C++内部缺少这一机制,C++毫不客气的对你说:“你提醒我给一个对象分配空间,那也得麻烦你提醒我将它释放(delete)。于是便有:

    class myclass
    {
        public:
            myclass()
            {
                cout << "构造函数" <<endl;
            }
            ~myclass()
            {
                cout << "析构函数" <<endl;
            }
    };
    
    int main()
    {
        myclass *mc;
        mc =new myclass();
        delete mc;
        return 0;
    }

    执行结果:

    图1

    所以如果是指针在new之后需要手动释放资源。在较大型的工程当中,资源的释放很重要,因为涉及的数据量比较多,稍有不慎,就会造成资源的浪费和泄露之类的问题,从现在起你就应该养成把握资源的好习惯。


    条款20:宁以pass-by-reference-to-const替换pass-by-value。——Scott Meyers

    //即:宁可用(常)引用传递替换值传递。

    为什么要在这里说在函数当中使用“常引用”,固然它跟析构函数有很大的牵连。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using  namespace std;
    
    class myclass
    {
        public:
            myclass()
            {
                cout << "构造函数" <<endl;
            }
            ~myclass()
            {
                cout << "析构函数" <<endl;
            }
    
    };
    
    void fx(myclass mc)
    {
    
    }
    
    int main()
    {
        myclass mc;
        fx(mc);
        return 0;
    }

    执行结果:

    结果很明朗,function函数内对myclass类的对象mc作了一次复制(浅复制而已)而造出了另一个对象,也就是函数内的对象副本;调用函数的时候,如果选择是传值调用,那么会有参数副本被复制到函数的栈区。

    因为这里调用的myclass类默认的copy构造函数,而不是调用上面myclass类的构造函数,但我们都明白,无论是哪种,都了构造,都是需要花费时间的,先不管时间有多短;遇上析构函数那是必然的。再者,如果myclass类有n个父类,而它的父类又有几个参数需要构造析构,最后还需要层层析构......那这个花费的时间可就不能四舍五入啦。

    解决方法就是宁以pass-by-reference-to-const替换pass-by-value。我们这样:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using  namespace std;
    
    class myclass
    {
        public:
            myclass()
            {
                cout << "构造函数" <<endl;
            }
            ~myclass()
            {
                cout << "析构函数" <<endl;
            }
    
    };
    
    void fx(const myclass &mc)
    {
    
    }
    
    int main()
    {
        myclass mc;
        fx(mc);
        return 0;
    }

    结果让我们大吃一惊:

    这就是我们想要,而如果你怕function函数内会对mc做一些非法的事情,const可以把他拒之门外。太帅了,实在是太帅了。

  • 相关阅读:
    MVC HtmlHelper用法大全
    mysql查询结果输出到文件
    未能加载文件或程序集“Autofac, Version=3.4.0.0,
    IHttpModule接口
    演练:创建和注册自定义 HTTP 模块
    Tablespace for table '`pomelo`.`bag`' exists. Please DISCARD the tablespace before IMPORT.
    java开发知识IO知识之输入输出流以及文件
    Java开发知识之Java中的Map结构
    Java开发知识之Java中的集合Set接口以及子类应用
    Java开发知识之Java中的集合上List接口以及子类讲解.
  • 原文地址:https://www.cnblogs.com/kane0526/p/3585338.html
Copyright © 2020-2023  润新知