【发布时间】:2019-07-27 13:52:36
【问题描述】:
我正在阅读问题的答案。 C++ Singleton design pattern
answer 之一建议使用 shared_ptr 来保证多个静态对象访问单例对象时的生命周期。我注意到这里的shared_ptr是用new构造的,是按值返回的。
是否使用 new 进行 shared_ptr 构造 atomic/thread_safe?
我的第二个困惑是关于 RVO。我尝试在我的实现中创建两个单例对象。
shared_ptr 显示三个_Uses 和一个_Weak。我预计 _Uses 计数是两个。 Visual Studio 15.5.6 上的优化已完成。 RVO 在这里不起作用吗?
class Singleton
{
public:
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
static std::shared_ptr<Singleton> instance()
{
static std::shared_ptr<Singleton> s{new Singleton};
return s;
}
~Singleton() {}
private:
Singleton() {}
};
int main()
{
std::shared_ptr<Singleton> obj1 = Singleton::instance();
std::shared_ptr<Singleton> obj2 = Singleton::instance();
return 0;
}
【问题讨论】:
-
这里使用
shared_ptr是多余的。函数instance()内部的静态成员变量s的寿命比调用Singleton::instance() 创建的任何其他shared_ptr 的寿命都要长。因此,为什么不把它变成一个普通对象并返回一个引用。 -
@MartinYork 正如answer of this question 中所述,使用
shared_ptr有助于在多个静态对象使用它时保持单例的存活。 -
@MikevanDyke 正如我的评论中所述。它根本没有帮助。删除共享指针(并将其替换为引用),它将保持活动状态。答案只得到 12 票是有原因的。
-
@MartinYork 你是对的,我在想,如果一个单例有一个引用另一个单例的成员,如果第二个单例首先被销毁,则可能会有一个悬空引用。但是,如果第一个单例有引用,则给出创建顺序,因此也给出销毁顺序。
-
@MikevanDyke 没错。但是有一个极端情况。如果您在单例本身被销毁后从静态存储持续时间对象的析构函数访问单例(这是 shared_ptr 和参考版本的问题)。但是这个问题是可以解决的。我在这里写过:请参阅部分:破坏问题:在stackoverflow.com/a/335746/14065