是不是通过weak_ptr创建单例类的正确方法

时间:2013-04-22 05:54:21

标签: c++ c++11 singleton

我创建了一个父类来处理带有智能指针的单例模式:

.h文件:

template<class singleType>
class Singleton
{
public:
    static std::shared_ptr<singleType> GetInstance();

private:
    static std::weak_ptr<singleType> m_singleObject;
};

.cpp文件:

template<class singleType>
std::shared_ptr<singleType> Singleton<singleType>::GetInstance()
{
    auto shareObject = m_singleObject.Lock();
    if (!shareObject)
    {
        shareObject.reset(new singleType);
        m_singleObject = shareObject;
    }

    return shareObject;
}

不确定这是使用智能指针的正确方法吗? 有什么想法吗?

非常感谢

4 个答案:

答案 0 :(得分:4)

我做了一些研究,所以现在我会发一个答案。

代码看起来都应该工作,并且是智能指针的正确用法。唯一的问题是你究竟想要单身人士的行为。这应该像教科书单例EXCEPT一样行为,如果当前没有任何指针指向单例,它将自行删除。这种行为实际上取决于程序的实现。如果你想让singelton只在它使用时存在,那么我会说它去吧。

我会避免经常造成和破坏singelton,特别是如果建筑和解构特别密集。如果它不断被创建和删除,那么你可能会更好地使用更标准的单例实现。标准单例行为往往是单例仅在程序运行期间创建一次,并且永远不会被删除。

我认为这是一个聪明的实现,因为你有使用它,我可能不得不借用这个想法。

答案 1 :(得分:4)

您的代码不是线程安全的。

名称lock可能表示并发访问被阻止,但实际上没有这样的保证:当多个线程同时调用您的GetInstance函数时,您将获得多个实例,而不是保证单个实例。< / p>

您需要在GetInstance函数生命周期的整个持续时间内创建显式锁。请注意,这当然不是很有效。

答案 2 :(得分:3)

已经讨论了此实现的优缺点。但是有一堆错误:

1)由于这是一个模板,你必须将你的实现移动到标题中,否则链接器找不到它。

2)weak_ptr的.lock()函数不是大写字母。

3)不要忘记实例化

template<class singleType> 
std::weak_ptr<singleType> Singleton<singleType>::m_singleObject;

4)更好地使用shareObject = std::make_shared<singleType>(singleType());代替newhttp://herbsutter.com/gotw/_103/

5)正如Konrad所说:它不是线程安全的。

答案 3 :(得分:1)

据我所知,这应该没问题。您将避免乱序破坏问题,但在创建初始实例后创建新实例可能会出现问题。这个单例在任何时候都只有一个实例存活,但是在程序运行过程中,运行多个实例可能总体上存在。

这种破坏和娱乐在表现方面也可能是不受欢迎的,不仅仅是副作用。