Partagez un article de blog clair sur le mode singleton et utilisez la méthode std :: once_flag:
https://www.cnblogs.com/xuhuajie/p/11647164.html
Le mode singleton est divisé en deux modes: l'homme affamé et l'homme paresseux. La plupart des projets utilisent la méthode de l'homme paresseux. Même si l'homme affamé est naturellement thread-safe, il n'est pas nécessaire d'envisager la libération de la mémoire, mais parce que c'est l'homme affamé , il sera utilisé ou non. Faites une demande de mémoire, afin que tout le monde réfléchisse à des moyens d'optimiser la manière paresseuse.
Le mode homme paresseux résumé dans l'article de blog lié ci-dessus est le suivant:
class SingletonUsePtr2
{
SINGLETON_CTOR(SingletonUsePtr2);
public:
static SingletonUsePtr2& Instance()
{
static std::once_flag s_flag;
std::call_once(s_flag, [&]() {
_ptr.reset(new SingletonUsePtr2);
});
return *_ptr;
}
private:
static std::unique_ptr<SingletonUsePtr2> _ptr;
};
1. Utilisez des pointeurs intelligents pour libérer automatiquement des objets.
2. Utilisez std :: once_flag pour supprimer std :: lock_guard <std :: mutex> dans l'ancienne méthode d'écriture
Le style paresseux le plus simple, sûr et fiable, est réalisé. . . . . .
Plus le modèle:
template<typename T>
class SingletonBase
{
SINGLETON_CTOR(SingletonBase);
public:
static T& Instance()
{
static T t; //饿汉式
return t;
}
};
template<typename T>
class SingletonBaseLazy
{
SINGLETON_CTOR(SingletonBaseLazy);
public:
static T& Instance()
{
static std::once_flag flag;
std::call_once(flag, [&](){_ptr.reset(new T); });
return *_ptr;
}
static std::unique_ptr<T> _ptr;
};
template<typename T>
std::unique_ptr<T> SingletonBaseLazy<T>::_ptr;
Voici un exemple du cas unique écrit dans le projet Baidu apollo, qui adopte essentiellement cette forme:
#define DISALLOW_COPY_AND_ASSIGN(classname) \
classname(const classname &) = delete; \
classname &operator=(const classname &) = delete;
#define DECLARE_SINGLETON(classname) \
public: \
static classname *Instance(bool create_if_needed = true) { \
static classname *instance = nullptr; \
if (!instance && create_if_needed) { \
static std::once_flag flag; \
std::call_once(flag, \
[&] { instance = new (std::nothrow) classname(); }); \
} \
return instance; \
} \
\
static void CleanUp() { \
auto instance = Instance(false); \
if (instance != nullptr) { \
CallShutdown(instance); \
} \
} \
\
private: \
classname(); \
DISALLOW_COPY_AND_ASSIGN(classname)