1

我有一个单身课程。我正在创建它的一个对象。使用它。一旦超出范围,就会调用析构函数。

再次创建一个新对象,因为 instanceFlag 为 false,它将再次分配新内存。

#include <iostream>

using namespace std;

class Singleton
{
private:
    static bool instanceFlag;
    static Singleton *single;
    Singleton()
    {
        //private constructor
    }
public:
    static Singleton* getInstance()
    {
        if(! instanceFlag)
        {
            single = new Singleton();
            instanceFlag = true;
            return single;
        }
        else
        {
            return single;
        }
    }
    void method()
    {
        cout << "Method of the singleton class" << endl;
    }
    ~Singleton()
    {
        instanceFlag = false;
    }
};

bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;



int main()
{
    Singleton *sc1,*sc2;
    {
        sc1 = Singleton::getInstance();
        sc1->method();
        delete sc1;
    }
    sc2 = Singleton::getInstance();
    sc2->method();

    return 0;
}

我的疑问是旧记忆会发生什么?我认为它是内存泄漏。如果是,如何在给定的代码中解决这个问题?

任何评论都将有助于理解内部结构。

4

5 回答 5

2

指针是包含内存中某物地址的变量。像任何其他变量一样,指针可以超出范围,但这与它所指向的信息无关。这就是泄漏发生的方式。

{
    char* p = new char[128];
}

p超出范围时,分配的地址消失,但分配保持不变;它仍然被分配,它的内容不受影响,就像扔掉一个信封会影响它寄给它的房子一样。

为了解决这个问题,你需要一些具有引用计数的东西,比如std::shared_ptr/std::weak_ptr或一个 RAII 容器std::unique_ptr,等等。有一个析构函数超出范围的东西。

最好用引用来实现单例模式。

class Singleton {
    Singleton() {
        // constructor code...
    }
    static Singleton s_singleton;
public:
    static Singleton& GetSingleton() {
        return s_singleton;
    }
};

或者

class Singleton {
    Singleton() = delete; // if you don't have a ctor, lets not have one at all.
public:
    static Singleton& GetSingleton() {
        static singleton;
        return singleton;
    }
};
于 2013-10-27T05:44:23.737 回答
0

我使用易于使用的 valgrind,它用于检测内存泄漏。 http://valgrind.org/docs/manual/quick-start.html

请参阅 headfirst c 教程以检测内存泄漏。

于 2013-10-27T05:38:09.743 回答
0

sc1并且sc2是指针,它们不是Singleton对象。Singleton::~Singleton()当它们超出范围时没有调用。

你的问题在别处。删除时sc1,您没有设置Singleton::instanceFlagfalse. 这意味着sc2->method()取消引用指向已删除对象的指针。

您应该将析构函数设为私有,并引入一个新的成员函数来删除对象。另外,你真的不需要Singleton::instanceFlag. 只需检查Singleton::single == NULL. 删除时,再次将其设置为 NULL。

于 2013-10-27T05:43:57.053 回答
0

首先,你实现单例模式的方式是错误的,

if(! instanceFlag)
{
    single = new Singleton();
    instanceFlag = true;
    return single;
}
else
{
    return single;
}

单例模式的重点不是有多个类的实例,而是只有一个。使用像上面这样的标志不是一个好的实现,您没有将标志设置为 true 并因此重新分配单例类,这确实违反了单例模式的规则

你可以使用类似下面的东西

==================================================== =========

public:
    static Singleton* getInstance()
    {
        if(! single )//check if class is already instantiated once (allocation already 
          //done)
        {
            single = new Singleton();
            instanceFlag = true;
        }
            return single;
    }

或者你也可以使用非指针

public:
    static Singleton& getInstance()
    {
        static Singleton single
        return single;
    }
于 2020-10-08T08:16:27.790 回答
-2

单例不应该被删除。

你的问题已经回答了

于 2013-10-27T05:41:20.177 回答