【问题标题】:Manual destructor call In Singleton Pattern : Invoked multiple times单例模式中的手动析构函数调用:多次调用
【发布时间】:2018-12-19 23:42:16
【问题描述】:

我试图编写一个显示当前时间的单例模式。通过调用静态成员函数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. 使用智能指针 - 在这种情况下,这些指针周围有一个析构函数并自动调用它

更新:

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

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

【问题讨论】:

  • (*global_time_variable).~current_date_time(); 调用它,delete global_time_variable; 再次调用它,这将导致无限递归。
  • @tkausl 愚蠢的我没有注意到它。我想不叫它是理想的。在什么情况下谁删除分配的内存?

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


【解决方案1】:

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

一般而言,析构函数由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;
}

【讨论】:

    猜你喜欢
    • 2014-05-18
    • 2021-04-24
    • 2012-07-12
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 2014-01-15
    • 2014-08-22
    • 2015-03-24
    相关资源
    最近更新 更多