【问题标题】:Is Singleton object returned through shared_ptr thread-safe?通过 shared_ptr 返回的 Singleton 对象是线程安全的吗?
【发布时间】: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

标签: c++ singleton atomic rvo


【解决方案1】:

是否使用 new 进行 shared_ptr 构造 atomic/thread_safe?

是的,shared_ptr 的创建是线程安全的,因为 static 初始化是线程安全的(另请参阅 this question

shared_ptr 显示三个_Uses 和一个_Weak。我预计 _Uses 计数是两个。 Visual Studio 15.5.6 上的优化已完成。 RVO 在这里不起作用吗?

您的使用次数为 3,因为 shared_ptr 被声明为 static,这意味着当它被初始化时,对象被创建,因此使用次数增加了 1(两个 @987654326 为 +2 @ 主要)。只有在 static shared_ptr 被销毁时,此使用计数才会再次减少,并且在程序终止时会发生这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 1970-01-01
    相关资源
    最近更新 更多