zoukankan      html  css  js  c++  java
  • 实战:单例的析构,为什么可以析构,重复析构等注意事项

    1.为什么可以析构?

    我对单例模式的理解:

    在单例类对象的生命周期内,只有一个单例类的对象,所以我可以让单例类对象生,也可以让它死,只要保证单例类对象生的时候,只有一个对象就行。

    让单例类对象死,就得需要接口,即在外部调用delete。

    2.单例的析构-实验, 以及注意事项

    注意事项: 不要重复调用析构函数,那样会导致程序奔溃

    代码:

    singleton_delete.cpp

    #include <iostream>
    #include "singleton_delete.hpp"
    #include <unistd.h>
    using namespace std;
    
    key_inputdev* key_inputdev::pkey_inputdev_instance = NULL;
    
    key_inputdev::key_inputdev() {    
        cout << "key_inputdev() Created !!" << endl;
    }
    
    key_inputdev::~key_inputdev() { 
        cout << "~key_inputdev() Gone !!" << endl;
        //delete pkey_inputdev_instance;  
       // 实测,main函数内deletedelete单例指针以后,这里析构函数内就不需要再次delete了。
       //     在main函数内delete单例指针后就已经释放了该类对象的内存。
        pkey_inputdev_instance = NULL;
    }
    
    key_inputdev* key_inputdev::pkey_inputdev_construct_instance(){
        //boost::unique_lock<boost::mutex> lock(mutex_singleton);
        if(pkey_inputdev_instance == NULL)  {
    
            std::cout << "Go To Create the key_inputdev " <<  std::endl;
            pkey_inputdev_instance = new key_inputdev;
        }
        return pkey_inputdev_instance;
    }
    int main(){
    
      while(1){
       key_inputdev*  pobj = key_inputdev::pkey_inputdev_construct_instance();
       delete pobj;
    
       sleep(1);
       cout << endl << endl;
    
      }
      return 0;
    }

    singleton_delete.hpp

    #ifndef singleton_delete_hpp
    #define singleton_delete_hpp
    
    class key_inputdev{
         
       key_inputdev(); 
    public:
        ~key_inputdev();
        static key_inputdev* pkey_inputdev_construct_instance();
    
        static key_inputdev* pkey_inputdev_instance;
    };
    
    #endif

    makefile

    .PHONY : do
    
    do:
        g++ *.cpp *.hpp -o ab
        #mips-linux-gnu-g++  *.cpp  *.hpp  -o  ab

    下面是代码截图:

     为什么不能在单例类的析构函数内再次调用delete单例类指针? 

     知识点,需要深刻理解delete的含义: delete提供两个功能=》1,根据后面跟的地址值来释放内存     2,调用析构函数。

    因为那样会造成反复调用单例类的析构函数,形成套娃现象,导致程序奔溃。

    在搞不清楚一些内存是否已经释放的情况下,有这样一个检测内存泄漏的小技巧: 

    再次尝试delete那片内存,如果程序运行奔溃,说明已经是二次重复释放了,如果程序正常运行,说明之前的内存并未释放。

    3.增补实验

     在有些情况下我们需要在析构函数内部去释放内存,这是很基本的常识:

     析构函数的函数体的职责是去释放类对象构造时以及工作过程中申请到的系统资源,因为此时类对象的生命周期结束了,所占资源要归还给操作系统!

     下面贴一个例子作为补充。

    #include <iostream>
    
    class myclass{
        int* pri;
    public:
        myclass(){
        pri = new int(100);
        }
        ~myclass(){
        delete pri;
        }
    
        int* GetP(){ // 不合理的接口
        return pri;
        }
    };
    
    int main(){
      myclass* pobj = new myclass;
    #if 0  
      delete pobj; // 代码运行无段错误,且pobj对象的内存空间和pri所指向的内存,均被释放。
    #endif
    
    #if 0
      int* p = pobj->GetP();
      delete p;   // 代码运行无段错误,pri所指向的内存被释放。
    #endif
    
    #if 1
      int* p = pobj->GetP();
      delete p; // 代码运行出现段错误,delete p和 delete pobj发生了冲突,导致pri的内存被重复释放。
      delete pobj;
    #endif
    
      return 0;
    }

    .

    /************* 社会的有色眼光是:博士生、研究生、本科生、车间工人; 重点大学高材生、普通院校、二流院校、野鸡大学; 年薪百万、五十万、五万; 这些都只是帽子,可以失败千百次,但我和社会都觉得,人只要成功一次,就能换一顶帽子,只是社会看不见你之前的失败的帽子。 当然,换帽子决不是最终目的,走好自己的路就行。 杭州.大话西游 *******/
  • 相关阅读:
    SQL多表组合查询
    软件测试基础知识点
    Jenkins可持续集成Python自动化脚本
    自动化总结(三) Unittest的应用2
    unittest单元测试2(转载)
    unittest单元测试(转载)
    自动化总结(二) Unittest的应用
    自动化测试小结(一)
    初识ES数据库(转载)
    功能测试小结(三)
  • 原文地址:https://www.cnblogs.com/happybirthdaytoyou/p/13820815.html
Copyright © 2011-2022 走看看