编辑:对不起,我的问题不明确,为什么书籍/文章更喜欢实施#1而不是实施#2?
使用指针实现Singleton类与使用静态对象相比有什么实际优势?为什么大多数书都喜欢这个
class Singleton
{
private:
static Singleton *p_inst;
Singleton();
public:
static Singleton * instance()
{
if (!p_inst)
{
p_inst = new Singleton();
}
return p_inst;
}
};
这个
class Singleton
{
public:
static Singleton& Instance()
{
static Singleton inst;
return inst;
}
protected:
Singleton(); // Prevent construction
Singleton(const Singleton&); // Prevent construction by copying
Singleton& operator=(const Singleton&); // Prevent assignment
~Singleton(); // Prevent unwanted destruction
};
答案 0 :(得分:17)
为什么书籍/文章更喜欢实施#1而不是实施#2?
因为大多数描述Singleton反模式的文章在尝试在C ++中安全地实现它时并不完全理解所有隐藏的危险。要做到这一点非常困难。
使用指针实现Singleton类与使用静态对象相比有什么实际优势?
使用带有new
但没有delete
的指针可确保永远不会销毁该对象,因此在其生命周期结束后不存在访问它的危险。结合“懒惰”创建,第一次访问它,这可以保证所有访问都是有效的对象。缺点是创建不是线程安全的,并且在程序结束时不会释放它获取的对象和任何资源。
使用本地静态对象,在任何支持C ++ 11线程模型的编译器上创建都是线程安全的。此外,该对象将在程序结束时被销毁。但是,可以在破坏后访问对象(例如从另一个静态对象的析构函数),这可能会导致令人讨厌的错误。
最佳选择是尽可能避免静态数据和全局可访问数据。特别是,永远不要使用Singleton反模式;它将全局静态数据与奇怪的实例化限制相结合,使测试变得不必要。
答案 1 :(得分:8)
第二个版本(使用本地静态变量)具有显着的优势。
它不需要使用免费存储,因此不会被检测为内存泄漏。它是线程安全的(在C++11
中)。它更短更简单。
唯一的缺点是它不可能使其成为线程安全(对于前C ++ 11编译器),并且它不会为您提供显式销毁单例实例的选项。
答案 2 :(得分:4)
我总是更喜欢第二个,但第一个确实有一些潜在的有趣优势: -
清晰度 - 指针检查为空是有效的 构造静态时编译器在底层做了什么 对象。从“学习”的角度来看,它具有指导意义 了解在方法中使用静态对象时发生的情况 范围。
延迟分配 - 在第一种情况下,Singleton对象是 堆分配。如果您的函数永远不会运行,则该对象永远不会 构建,永远不会消耗记忆。但是,在第二种情况下, 内存由链接器分配,用于在之前保存对象 程序启动,即使“构造”是懒惰的。
答案 3 :(得分:3)
第二个具有非确定性破坏。第一个,你可以控制何时删除指针,如果有的话。
第一个构造当然不是线程安全的,但可以使用boost::call_once
(或std::call_once
如果可用)来实现
第二个结构很常见,许多编译器使它成为线程安全的,即使在技术上它不符合标准(尽管按照标准,对象应该只创建一次,我不确定标准的视图在另一个线程使用它之前完成构造。)
如果破坏顺序没有问题,那么你可以继续使用静态版本,只要你的编译器保证它是线程安全的。
答案 4 :(得分:2)
第二个例子名为“Meyers'Singleton”,因为它首先在“Effective C ++”或“More Effective C ++”中发布。我不确定是哪一个,但两者都是在“设计模式”之后发布的 - 所以四人帮也可能在他们的书写完时没有意识到第二种模式。
此外,第一种方法对于其他语言来说更为标准 - 你可以用Java或C#做第一种方法,但不能用第二种做法,所以来自不同背景的人可能是第一种更有名的人的另一个原因
在技术方面,使用第一种方法可以控制单身人士何时被摧毁,但这也会给你带来很多麻烦。
答案 5 :(得分:1)
一个优点是您不必检查单例是否已经实例化。
另一个原因是您不必担心取消分配任何内存。
答案 6 :(得分:-3)
非本地静态怎么样?有人看到这个问题吗?
class Singleton
{
static Singleton singleton;
Singleton();
// etc
public:
static Singleton &Instance() { return singleton; }
};
Singleton Singleton::singleton;
// etc