我的具体问题是,在 C++ 中实现单例类时,以下两个代码在性能、附带问题或其他方面是否存在实质性差异:
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 没有为取消引用生成额外的机器代码。与指针区分似乎只是语法问题。)
更新:
我有一些有趣的答案和评论,我试图在这里总结它们。(建议感兴趣的人阅读详细答案。):
- 在使用静态局部变量的单例中,类析构函数在进程终止时自动调用,而在动态分配的情况下,您必须在某个时候以某种方式管理对象销毁,例如通过使用智能指针:
static singleton& getInstance() {
static std::auto_ptr<singleton> instance (new singleton());
return *instance.get();
}
使用动态分配的单例比静态单例变量“更懒惰”,因为在后一种情况下,单例对象所需的内存(总是?)在进程启动时保留(作为加载程序所需的整个内存的一部分) 并且只有单例构造函数的调用被推迟到
getInstance()
调用时。这可能sizeof(singleton)
很重要。两者在 C++11 中都是线程安全的。但是对于早期版本的 C++,它是特定于实现的。
动态分配情况使用一级间接访问单例对象,而在静态单例对象情况下,对象的直接地址是在编译时确定和硬编码的。
PS:我已经根据@TonyD 的回答更正了我在原始帖子中使用的术语。