2017-10-15 86 views
-1

作为一个例子,我们来谈谈使用new(在第一次调用getInstance()方法时创建实际实例,而不是使用静态字段)的单例实现,它让我明白永远不会释放内存。 。那就要做到这一点的应用程序关闭,以便系统能够释放该内存高达反正权利之前在程序结束之前不能释放内存有多糟?

除了糟糕的设计,确实这种做法有什么实际的缺点

编辑:广告的评论 - 所有有效点? ,谢谢你们,所以让我来问一下 - 对于单个线程应用程序和POD单例类,是否有任何实际的缺点?理论上讲,我不打算真的这样做。

+3

这是一个坏习惯,这是肯定的。除此之外,它确实取决于操作系统。一旦进程终止,大多数主要的PC操作系统都会释放一个进程的所有资源。如果您在运行时使用泄漏检测器查找内存泄漏,则在进程终止之前不释放内存将导致误报。 –

+3

取决于你是否拥有new'd可能拥有外部资源,而不仅仅是内存,例如。文件句柄等。您可能想要很好地关闭这些资源,而不是放弃它们。 –

+1

有一个原因,你应该总是使用'静态'方法来处理单身:线程安全(在其他一些方面)... – Rakete1111

回答

0

对于单线程应用程序和POD单例类是否有任何实际的缺点?从理论上讲,我不会那么做。

standardese

[C++ 14 - 对象寿命-4]对于类型与非平凡的析构函数的目的,不要求该程序调用析构函数明确地前对象占用的存储空间被重用或释放;但是,如果没有显式调用析构函数或者没有使用delete-expression(5.3.5)释放存储,则不应该隐式调用析构函数,并且任何依赖析构函数产生的副作用的程序有未定义的行为。

其中dtor在自动/静态变量等隐式调用。因此,(假设一个新的表达式被用来构造对象)被调用的分配函数的运行时实现可以释放内存并让对象在遗忘时衰减,只要没有可观察的效果依赖于它的破坏(对于含有微不足道的类型的类型来说,这是非常正确的)。

+0

这并没有说是否可以释放存储。 – rustyx

+0

@rustyx如果运行时在释放内存时释放内存我的答案表示没有UB发生;如果运行时没有,那么会发生什么是未定义的;) –

0

对所有单身类型使用schwartz计数器。这就是std::cout的实现方式。

优点:

  • 线程安全

  • 正确的初始化命令时,单身取决于对方

  • 正确的破坏顺序在程序终止保证

  • 不使用堆

  • 100%符合C++ 98,C++ 03,C++ 11,C++ 14,C++ 17 ...

  • 不需要难看的getInstance()函数。只需使用全局对象。

https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Nifty_Counter

至于标题问题:

如何坏右程序结束之前未释放内存?

当程序在管理进程内存的操作系统下运行时,释放内存并不是那么糟糕。然而,单件做的其他事情可能包括冲洗IO缓冲区(例如std::cout,std::cerr)。这可能是你想避免丢失的东西。

+0

线程安全性如何? https://stackoverflow.com/questions/39393850/can-num-be-atomic-for-int-num – stark

+0

@stark因为所有的单例都按正确的顺序初始化,所以任何相关的线程都会发现它已经被初始化了。 –

+0

ok,但是属于不同TU的有序初始化序列可以同时发生,是不是?...如果是,参考计数器访问仍然应该同步 –