【问题标题】:Memory allocation, Singletons, and when to use/avoid them内存分配、单例以及何时使用/避免它们
【发布时间】:2013-03-28 18:33:40
【问题描述】:

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

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

准确定义“单例”的含义很重要。

就本论点而言,单例是任何不从堆栈开始即可到达的可变状态(即从静态或全局变量可到达)。

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

示例:

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

...

open() 或 stdout 呢?

这些是单例最糟糕的例子!
...

这意味着,基本上,mallocnewshared_ptr,或者任何你的语言用来访问堆内存的东西——所有这些都使用单例!

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

所以我的问题是,内存分配是规则的一个例外(为什么?),还是也是单例的一个坏例子?

我如何确定单身人士的新用途是否属于同一“例外”类别?

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

【问题讨论】:

  • 单身人士的定义很奇怪。它似乎根本不包括它的“单一”部分。编辑:它几乎不符合单例的实际定义。 =/
  • @sftrabbit:它似乎关注与您在其他定义(“全局状态”)中看到的单例相同的问题,并且内存管理当然涉及 single(默认) 具有全局状态的内存管理器,对吧?
  • 是的,他们定义的只是全局状态。
  • 好吧,malloc(等)没有可观察到的副作用(除了二进制“它是否可以分配内存”)。因此,尚不清楚假设的非单例malloc 会带来什么优势。但最终,只有一个地址空间(在标准操作系统中)!这个事实需要以某种方式表达......
  • @sftrabbit:呃,我的意思是,每种语言的运行时内存管理器都是单例的例子吗?根据上面的定义,但如果你不这么认为,那么我很想知道为什么! (或许可以回答?)

标签: c++ oop language-agnostic singleton


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多