【问题标题】:Singleton destructor not called?未调用单例析构函数?
【发布时间】:2017-04-19 19:44:10
【问题描述】:

所以我写了一个简单的单例类。当我创建一个对象时,会调用构造函数,但它的析构函数(释放对象)似乎在超出范围时不会被调用。

#include <iostream>

using namespace std;

class Singleton {
public:
    static Singleton &getInstance( )
    {
        if (instance == nullptr) {
            cout << "Creating instance.\n";
            instance = new Singleton();
        }
        return *instance;
    }
    static void destroyInstance( )
    {
        if (instance != nullptr) {
            cout << "Destroying instance.\n";
            delete instance;
            instance = nullptr;
        }
    }
    ~Singleton( )
    {
        if (instance != nullptr) {
            cout << "Destroying instance.\n";
            delete instance;
            instance = nullptr;
        }
    }
private:
    Singleton( ) { }

    static Singleton *instance;
};
Singleton *Singleton::instance = nullptr;

int main( )
{
    Singleton &singleton = Singleton::getInstance();

    //singleton.destroyInstance();

    return 0;
}

使用析构函数代码,程序只输出这个。

Creating instance.

如果我注释掉析构函数并使用destroyInstance() 函数,它会输出这个。

Creating instance.
Destorying instance.

为什么要这样做?

编辑:我是个白痴。只是忽略了一堆东西。这个问题也可能被删除,因为它并不是那么有用。

【问题讨论】:

  • 我很困惑。如果您不调用delete,您希望什么机制对您的单身人士delete 起作用?实现析构函数只是描述了当一个实例被销毁时会发生什么,它对 ifwhen 它被销毁没有任何影响。
  • 你的析构函数至少会失败一次。
  • 指针超出范围时不会被删除。通常一个单例会被初始化一次。在自己的析构函数中调用delete 也可能是一个非常糟糕的主意。
  • @FrançoisAndrieux 我真的不知道。据我了解,删除使用new 分配的内容只是一个好习惯。虽然我仍然会将析构函数用于其他事情。
  • @TomSmale 所以我写了一个简单的单例类——不像Meyer's singleton那么简单

标签: c++


【解决方案1】:

你的析构函数中的逻辑是奇怪的递归:

~Singleton( )
{
    if (instance != nullptr) {
        cout << "Destroying instance.\n";
        delete instance;
        instance = nullptr;
    }
}

您在析构函数中对实例调用 delete,但调用 delete 是触发析构函数运行的原因!

您说析构函数在超出范围时不会被调用,但请记住您使用 new 创建了单例;当作用域结束时,此类对象不再自动调用其析构函数。

除非你真的非常需要在程序中间销毁并重新创建你的单例(在我的经验中非常罕见),否则只需像这样创建你的单例:

static Singleton& getInstance() {
    static Singleton s;
    return s;
}

摆脱destroyInstance,让析构函数按照它应该的方式自行清理,而不用担心静态实例。

【讨论】:

  • 在我看来,这不是需要在运行时销毁和重新创建它的情况,而是一种懒惰创建的情况。
【解决方案2】:

使用智能指针 (#include &lt;memory&gt;)

#include <iostream>
#include <memory>

using namespace std;

class Singleton {
public:
    static Singleton &getInstance()
    {
        if (instance == nullptr) {
            cout << "Creating instance.\n";
            instance = std::shared_ptr<Singleton>(new Singleton());
        }
        return *instance;
    }
    static void destroyInstance()
    {
        if (instance != nullptr) {
            cout << "Destroying instance.\n";
            instance.reset();
            instance = nullptr;
        }
    }
    ~Singleton()
    {
        if (instance != nullptr) {
            cout << "Destroying instance.\n";
            instance.reset();
            instance = nullptr;
        }
    }
private:
    Singleton() { }

    static std::shared_ptr<Singleton> instance;
};
std::shared_ptr<Singleton> Singleton::instance = nullptr;

int main()
{
    Singleton &singleton = Singleton::getInstance();

    //singleton.destroyInstance();

    return 0;
}

【讨论】:

    猜你喜欢
    • 2014-05-18
    • 2010-10-16
    • 2023-04-08
    • 2017-04-28
    • 2013-07-07
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多