在Singleton Pattern中手动进行析构函数调用:多次调用

时间:2018-07-11 20:37:45

标签: c++ design-patterns memory-leaks destructor static-variables

我试图编写一个显示当前时间的单例模式。通过调用静态成员函数destroy_instance()删除分配给静态指针变量global_time_variable的堆内存时会出现问题。

class current_date_time {

  private:

    current_date_time() {
       std::cout << "constructor invoked!!\n";
    };

    ~current_date_time() {
       std::cout << "destructor invoked!!\n";
       delete global_time_variable;
    };

  public:

    static void create_instance();
    static void destroy_instance();
    static current_date_time* global_time_variable;

    void time_output(){
      std::time_t t = std::time(nullptr);
      std::tm tm = *std::localtime(&t);
      std::cout << std::put_time(&tm, "%c %Z") << "\n";
    }

};


current_date_time* current_date_time::global_time_variable = NULL;

void current_date_time::create_instance() {
   if(current_date_time::global_time_variable == NULL)
      global_time_variable =  new current_date_time();
}

void current_date_time::destroy_instance() {
    (*global_time_variable).~current_date_time();
}


int main() {

   current_date_time::create_instance();
   current_date_time::global_time_variable->time_output();
   current_date_time::destroy_instance();
   return 0;
}

我很想知道为什么析构函数会被多次调用?

关于詹姆斯·坎泽(James Kanze)对问题C++ Deleting Static Data的回答 其他可能的选项是:

  1. 不尝试手动调用-在这种情况下,对象保留在堆中,我不确定谁将其删除
  2. 使用智能指针-在这种情况下,这些指针周围有一个析构函数,并且会自动对其进行调用

更新:

我的第二个问题是:如果我不调用析构函数(这似乎是推荐的选项之一),会不会导致内存泄漏?< / strong>

由于静态变量在程序生存期之后会被销毁,而 global_time_variable 指向的对象不会被销毁。

1 个答案:

答案 0 :(得分:0)

由于new是在create_instance中被调用的,因此delete应该在destroy_instance中被调用,而不是手动的析构函数调用。

通常,析构函数由delete调用,因此它们自己不应该在被破坏的对象上调用delete

#include <iomanip>
#include <ctime>
#include <stdio.h>
#include <iostream>
#include <string.h>

class current_date_time {

  private:

    current_date_time() {
       std::cout << "constructor invoked!!\n";
    };

    ~current_date_time() {
       std::cout << "destructor invoked!!\n";
    };

  public:

    static void create_instance();
    static void destroy_instance();
    static current_date_time* global_time_variable;

    void time_output(){
      std::time_t t = std::time(nullptr);
      std::tm tm = *std::localtime(&t);
      std::cout << std::put_time(&tm, "%c %Z") << "\n";
    }

};


current_date_time* current_date_time::global_time_variable = NULL;

void current_date_time::create_instance() {
   if(current_date_time::global_time_variable == NULL)
      global_time_variable =  new current_date_time();
}

void current_date_time::destroy_instance() {
    delete global_time_variable;
    global_time_variable = NULL;
}


int main() {

   current_date_time::create_instance();
   current_date_time::global_time_variable->time_output();
   current_date_time::destroy_instance();
   return 0;
}