Singleton的析构函数

时间:2009-09-26 11:39:44

标签: c++ singleton

问题:我应该为具有程序范围的单例编写析构函数(在程序启动时生效并在程序结束时死亡)

明细:

我处于两难境地

“我应该为单身人士课程编写析构函数吗?”

1)这个类有程序范围 2)类在堆上使用大量内存,因此释放需要时间

当用户退出程序时,响应速度应该很快,那么为什么要花时间释放这个单例所占用的内存,因为当程序结束时会释放内存。

6 个答案:

答案 0 :(得分:3)

如果释放内存需要很长时间,请不要这样做。这可能是一个大而耗时的问题,特别是如果释放内存导致大量缓存未命中。操作系统将完成这项工作(当然,如果您在实际执行此操作的系统上运行)。

但是,如果析构函数确定了某些资源(例如,解锁文件或硬件),并且使用“资源获取是初始化”,则必须确保调用正确的析构函数(例如,在main()函数返回后调用静态对象。 如果你的单例内部分配的某些对象也锁定了资源,那么这就行了!

因此,在大多数情况下,最好为这样的对象实际编写析构函数并使其释放内存可选


提出这个问题的

SSS决定不写下析构函数。但是,我想再多说一点,这不是最好的解决方案。

不释放静态对象的内存(让我们称之为“静态”)是一种非常微妙的优化,它与常识以及人们通常如何编写程序相矛盾。你的代码,分配内存,只是没有析构函数,看起来很奇怪。同行会认为这个班级编写得很糟糕,往往会看到错误(当他们在另一个班级时)。

相反,您应该遵循通用编码标准,这些标准规定C ++中的内存管理应该是正确的。写一个析构函数,并且只有在它显示它有一个显着的提升而不是解除分配之后,包装它的代码不被调用。

不释放内存的意图必须是显式

MySingleton::~MySingleton()
{
#ifndef RELEASE
  // The memory will be released by OS when program terminates!
  delete ptr1;
  delete ptr2;
#endif
}

甚至

MySingleton::~MySingleton()
{
  // We don't do anything here.
  // The memory will be released by OS when program terminates!
}

但是析构函数最好坚持下去。

答案 1 :(得分:2)

听起来你正在创建一个God Object,所以重新考虑你班级的设计可能会有所帮助。

是否添加析构函数取决于是否值得释放性能并最终重新分配内存。

答案 2 :(得分:2)

C ++语言不保证在程序终止时回收内存,但任何一半体面的操作系统都会毫无问题地进行回收。

是的,如果

  • 你正在运行一半体面的操作系统,
  • 析构函数除了释放内存之外别无其他任何东西

然后是的,你可以省略析构函数,泄漏内存,并依赖操作系统来清理你。

明显的缺点是各种调试工具可能会尖叫并对内存泄漏大吼大叫。

当然,一个稍微更基本的问题是为什么要创建一个分配那么多内存的单例?

这对我来说听起来很糟糕。

答案 3 :(得分:2)

以正确的方式实现析构函数,并且是最易维护的版本。然后测量(创建一个只创建单例并退出的可执行文件)释放内存所需的实际时间。

在确定正确删除成本的确凿事实之后,请不要编写错误的代码。如果需要一些可测量的时间,请将其视为相对于程序运行时间的相对度量。在大多数情况下,应用程序所需的处理将远远超过释放内存所需的时间。

如果您仍然认为需要花费太多时间,请考虑一下普通用户会考虑太多时间,用户打开和关闭应用程序的次数,如果它确实相当于任何东西。

如果最后你认为它太多了,你冒的风险是,在以后的某个时间内应用程序将被修改,单例可以获取外部资源而不是释放它们 - 这对于文件锁特别糟糕。

那些牺牲表现正确性的人不应该

答案 4 :(得分:0)

如果您在Windows操作系统下运行,当应用程序关闭时,任何进程占用的所有内存/资源都将被回收,因此恕我直言无关紧要

答案 5 :(得分:-2)

正如所指出的那样,操作系统最终释放内存,但是你真的想信任它来管理吗?至少在显式破坏的情况下,一个错误/设计糟糕的内存管理器有更多的机会来实现它。

它有两次机会让它正确。