Правильно ли вы создаете класс sinlgeton by weak_ptr

Я создаю родительский класс для обработки шаблона 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;
}

Не уверен, что это правильный способ использования умного указателя? Любая идея?

Большое спасибо

Ответ 1

Проценты и минусы этой реализации уже обсуждаются. Но есть куча ошибок:

1) Поскольку это шаблон, вы должны перенести свою реализацию в заголовок, или компоновщик не может его найти.

2) Функция .lock() слабой_ptr не находится в капиталах.

3) Не забудьте создать экземпляр

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

4) Лучше использовать shareObject = std::make_shared<singleType>(singleType()); вместо new: http://herbsutter.com/gotw/_103/

5) Как сказал Конрад: он не защищен потоками.

Ответ 2

Я провел некоторое исследование, поэтому теперь отправлю ответ.

Код выглядит так, как будто он должен работать, и это правильное использование интеллектуальных указателей. Вопрос только в том, как именно вы хотите, чтобы синглтон себя вел. Это должно вести себя как учебник singleton EXCEPT для поведения, который, если в настоящее время нет указателя на синглтон, он удалит себя. Такое поведение действительно зависит от реализации вашей программы. Если вы хотите, чтобы singelton существовал только тогда, когда он используется, я бы сказал, что нужно пойти на это.

Я бы просто избегал создавать и разрушать singelton слишком часто, особенно если строительство и деконструкция особенно интенсивны. Если он постоянно создается и удаляется, вам, вероятно, лучше работать с более стандартной версией singleton. Стандартное поведение singleton имеет тенденцию к тому, что singleton создается только один раз во время работы программы и никогда не удаляется.

Я думаю, что это умная реализация, учитывая, что вы используете ее, и мне, возможно, придется занять эту идею.

Ответ 3

Ваш код не является потокобезопасным.

Имя lock может предполагать, что одновременный доступ блокируется, но на самом деле нет такой гарантии: когда несколько потоков одновременно вызывают функцию GetInstance, вы получите несколько экземпляров вместо того, чтобы гарантировать один.

Вам нужно создать явную блокировку для всей продолжительности жизни функции GetInstance. Обратите внимание, что это, конечно, не очень эффективно.

Ответ 4

Насколько мне известно, все должно быть хорошо. Вы избегаете проблем с уничтожением порядка, но может возникнуть проблема с созданием новых экземпляров после создания вашего первого экземпляра. Этот синглтон будет иметь только один экземпляр в любой момент, но в течение программы, запускающей более одного экземпляра, возможно, был жив в целом.

Это разрушение и отдых также могут быть нежелательными с точки зрения производительности, а не только в побочных эффектах.