Синглтонная реализация c ++ Мейер против call_once - PullRequest
6 голосов
/ 11 октября 2019

Ну, я использую синглтон в своем собственном проекте. Наиболее часто используемая одноэлементная реализация может быть синглом Мейера и использованием 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 для наиболее простой реализации одноэлементной реализации, все же думали о каком-то небольшом компоненте проекта, используя реализацию Майера. Мне просто интересно, есть ли какой-то принцип, которому нужно следовать, и каковы плюсы и минусы этих двух разных значений?

1 Ответ

4 голосов
/ 11 октября 2019

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

...