内存分配,单身人士,何时使用/避免它们

时间:2013-03-28 18:33:40

标签: c++ oop language-agnostic singleton

我遇到了this page,它对单身人士有一个非常好的,全面的概述。

而不是常见的“Singleton是一个具有私有构造函数且只有一个全局实例的类”,它描述了一个Singleton,如下所示:

  

准确定义“单身人士”的含义非常重要。

     

出于这个参数的目的,一个单例是任何可以在不从栈开始时可以访问的可变状态(即可以从静态变量或全局变量到达)。

     

通常,单例是作者期望只有一个实例的类。但是,出于我们的目的,任何全局可访问的对象都是重要的。

     

示例:

     
      
  • 操作某些共享可变状态的一组函数(或静态方法)构成一个单例。
  •   
  • 如果单例A提供对可变对象B的引用,那么B也是单例。
  •   
  • 这意味着单例集合的每个可变成员本身都是单例。
  •   
  • 即使全局可访问,可传递的不可变对象也不是单例。这是一个常数。
  •   
  • 假设代码是不可变的,不访问任何单例的独立函数本身并不是单例,
  •   
     

...

     

open()或stdout怎么样?

     

这些是单身人士最糟糕的例子之一!   ...

这实质上意味着mallocnewshared_ptr或您的语言用于访问堆内存的所有内容 - 所有这些都使用单身人士!

然而,没有人说我们需要避免堆分配。 内存分配似乎无处不在!即使在我引用的页面上,他们提到了open()stdout以及日志记录,但他们从未提及堆内存分配 - 这显然比记录器更“危险”,因为它不是单行道。

所以我的问题是,内存分配是规则的一个例外(为什么?),还是 是单身人士的坏榜样?

我如何决定Singletons的新用途是否属于同一“特殊”类别?

(由于显而易见的原因,标记为语言不可知,但也标记为C ++,因为我认为它与C ++特别相关,因为它允许用户修改new的行为并引入更多的全局状态。)

1 个答案:

答案 0 :(得分:1)

根据定义,您的程序只与一个外部世界交互。所以没有人会认为那不是单身人士的例子!

但从软件设计的角度来看,我会说好的/不好的只是一个问题“这会不会给我带来麻烦?”并且“我能做些什么吗?”。

对于像输出这样的东西,两者的答案都是“是”。在复杂的程序中,通过将输出封装在非单例对象中获得了相当大的好处(测试,依赖注入等)。对于像系统内存这样的东西,不是那么多。

你可以设法抽象出一些固有的耦合(事实上,操作系统,语言运行时,以及自定义分配器之类的东西在内存的情况下都会在某种程度上这样做)。将所有内存分配封装在对象后面也是有帮助的,以允许测试对内存不足情况的复杂应用程序响应。但你仍然无法完全消除全球耦合。