【发布时间】:2013-02-10 08:22:00
【问题描述】:
我的具体问题是,在 C++ 中实现singleton class 时,以下两个代码在性能、附带问题或其他方面是否存在实质性差异:
class singleton
{
// ...
static singleton& getInstance()
{
// allocating on heap
static singleton* pInstance = new singleton();
return *pInstance;
}
// ...
};
还有这个:
class singleton
{
// ...
static singleton& getInstance()
{
// using static variable
static singleton instance;
return instance;
}
// ...
};
(请注意,基于堆的实现中的取消引用不应影响性能,因为 AFAIK 没有为取消引用生成额外的机器代码。与指针区分开似乎只是语法问题。)
更新:
我有一些有趣的答案和 cmets,我试图在这里对其进行总结。 (建议有兴趣的人阅读详细答案。):
- 在使用 static 局部变量的单例中,类析构函数在进程终止时自动调用,而在 动态分配 的情况下,您必须以某种方式管理对象销毁有时,例如通过使用智能指针:
static singleton& getInstance() {
static std::auto_ptr<singleton> instance (new singleton());
return *instance.get();
}
使用动态分配的单例比静态单例变量“懒惰”,因为在后一种情况下,单例对象所需的内存(总是?)在进程启动时保留-up(作为加载程序所需的整个内存的一部分)并且仅调用单例构造函数被推迟到
getInstance()调用时间。当sizeof(singleton)很大时,这可能很重要。两者在 C++11 中都是线程安全的。但对于早期版本的 C++,它是特定于实现的。
-
动态分配情况使用一级间接访问单例对象,而在静态单例对象情况下,对象的直接地址是在编译时确定和硬编码的。
P.S.:我已根据 @TonyD 的回答更正了我在原始帖子中使用的术语。
【问题讨论】:
-
你比较过两者生成的程序集吗?
-
没有。如果您的意思是为两种不同的实现生成程序集,那么它们显然是不同的,因为一个在堆上分配,一个在加载/调用时初始化。如果您的意思是为取消引用而生成的程序集,不,我没有比较过。我只是这么想。
标签: c++ memory static singleton dynamic-memory-allocation