Ну, я использую синглтон в своем собственном проекте. Наиболее часто используемая одноэлементная реализация может быть синглом Мейера и использованием std :: call_once или pthread_once. Оба они являются поточно-ориентированными для параллельных вычислений
//Meyer's singleton
class MySingleton{
public:
static MySingleton& getInstance(){
static MySingleton instance;
// volatile int dummy{};
return instance;
}
private:
MySingleton()= default;
~MySingleton()= default;
MySingleton(const MySingleton&)= delete;
MySingleton& operator=(const MySingleton&)= delete;
};
//with call_once
class MySingleton{
public:
static MySingleton& getInstance(){
std::call_once(initInstanceFlag, &MySingleton::initSingleton);
// volatile int dummy{};
return *instance;
}
private:
MySingleton()= default;
~MySingleton()= default;
MySingleton(const MySingleton&)= delete;
MySingleton& operator=(const MySingleton&)= delete;
static MySingleton* instance;
static std::once_flag initInstanceFlag;
static void initSingleton(){
instance= new MySingleton;
}
};
MySingleton* MySingleton::instance= nullptr;
std::once_flag MySingleton::initInstanceFlag;
Имплементация Майера с использованием локальной статической переменной для обеспечения безопасности потока и возврата идентификатора экземпляра, в то время как последний достигается с помощью call_once и сохраняет указатель. В моем эксперименте имплиментация Мейера проходит немного быстрее. Но большинство проектов, использующих подход call_once для наиболее простой реализации одноэлементной реализации, все же думали о каком-то небольшом компоненте проекта, используя реализацию Майера. Мне просто интересно, есть ли какой-то принцип, которому нужно следовать, и каковы плюсы и минусы этих двух разных значений?