【问题标题】:how to delete singleton object如何删除单例对象
【发布时间】:2013-03-21 22:32:46
【问题描述】:

假设这个实现是单例模式(当然我们应该避免单例:这只是个问题),我一直在考虑创建静态对象。它是由new 运算符在堆上创建的,当然,但是它是如何被销毁的呢?在下面的例子中我们有一个泄漏,那么应该如何实现静态单例对象的删除?是否应该采用please_delete()公共接口,所以可以调用myC->please_delete()或者有其他方法可以实现吗?

class CC{
public:
    static CC* cObj(){
        if(c_ptr==NULL){
            c_ptr=new CC();
            return c_ptr;
        }else return c_ptr;
    }
    int getValue(){return value_;}
    void setValue(int val){value_=val;}
    ~CC(){cout<<"~CC";}
private:
    CC():value_(12345){cout<<"CC";}
    static CC* c_ptr;
    int value_;
};
// Allocating and initializing CC's
// static data member.  The pointer is being
// allocated - not the object itself.
CC *CC::c_ptr = 0;

int main(){
    //Singleton pattern
    CC* myC = CC::cObj();
    cout<<myC->getValue();
    return 0;
}

输出:CC12345

运行成功(总时间:67 毫秒)

我注意到我们确实可以像boost::shared_ptr&lt;CC&gt; bCptr(CC::cObj()); 一样在shared_ptr 中声明单例静态实例,但是单例模式根本没有提到删除对象的问题,所以也许还有其他方法?

【问题讨论】:

  • 单身人士喜欢这样吗?为什么不直接返回static CC
  • 我似乎错过了为 c_ptr 分配 CC 对象的行
  • 是的,当然,改变了,谢谢

标签: c++ design-patterns singleton


【解决方案1】:

Singleton 设计模式的一部分是它是坚不可摧的。

编辑:

关于可破坏性,有 2 种单例:

  1. 可破坏(应用程序破坏时它们会死)
  2. 坚不可摧(当机器损坏时它们会死)

无论哪种方式,如果构建正确,一旦创建了单例实例,它就会保留下来。这是对 Singleton 设计模式的主要批评之一。

这里有一些解决模式可破坏性方面的参考资料。

http://nicolabonelli.wordpress.com/2009/06/04/singleton-a-mirage-of-perfection/ http://www10.informatik.uni-erlangen.de/Teaching/Courses/SS2009/CPP/altmann.pdf http://sourcemaking.com/design_patterns/singleton http://sourcemaking.com/design_patterns/to_kill_a_singleton

【讨论】:

  • 我完全同意。让我们在航天器.stackexchage.com 上提出这个问题
  • 它是如何坚不可摧的?它不应该被称为然后泄漏吗?但是,其他应用程序仍然可以使用它吗?
  • 如果单例泄漏,则不适合用作航天器材料。
  • 单子实际上并没有泄漏,因为它们会牢牢固定在原位,直到整个航天器或应用程序被破坏。
  • 谢谢,现在我明白了宇宙飞船和单例删除
【解决方案2】:

经典的单例模式没有描述删除方面。

但是,如果我必须这样做,我会从一个简单的方法开始,如下所示(它不是万无一失的):

1) 类似于创建/检索单例对象的静态方法,比如createObject(),还有一个用于破坏单例对象的静态方法,比如destructObject()

2) 有一个计数器,用于统计系统中当前对象的数量;

  • 从 0 开始
  • createObject() 调用时,递增1
  • deleteObject() 调用时,它减1。
    • 如果达到 0,则调用 delete实际上破坏对象

【讨论】:

  • 与 shared_ptr 的唯一区别是计数器是全局的(在系统中不是使用此单例的单个应用程序)对吗?
  • 计数器也像实际对象一样是单例的。
【解决方案3】:

我不喜欢使用指针。

class Single
{
private:
   Single();

public:
   Single& Instance()
   {
      static Single the_instance;
      Return the_instance;
   }
};

这个单例将从调用Instance() 直到应用程序退出并执行静态对象的销毁。在这种情况下,将调用单例对象的析构函数。

实际上,即使在原始示例中使用指针时,操作系统也会在应用程序退出时回收内存。但是在这种情况下,对象的析构函数将不会被调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-28
    • 1970-01-01
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多