Ответ
Singleton — это порождающий паттерн проектирования, который гарантирует, что у класса существует только один экземпляр, и предоставляет к нему глобальную точку доступа.
В C++ его реализация сопряжена с рядом тонкостей, касающихся времени жизни, потокобезопасности и управления памятью.
Классическая потокобезопасная реализация на C++11 (Meyer's Singleton):
class Singleton {
public:
// Удаляем конструктор копирования и оператор присваивания
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// Статический метод, возвращающий ссылку на единственный экземпляр
static Singleton& getInstance() {
static Singleton instance; // Гарантированная потокобезопасная инициализация (C++11)
return instance;
}
void doSomething() {
// ... реализация методов
}
private:
Singleton() = default; // Приватный конструктор
~Singleton() = default;
};
// Использование:
Singleton::getInstance().doSomething();
Почему такая реализация предпочтительна:
- Потокобезопасность: Локальная статическая переменная внутри функции инициализируется гарантированно один раз, даже в многопоточной среде (требуется поддержка компилятора).
- Управление памятью: Объект создается при первом вызове
getInstance()(ленивая инициализация) и уничтожается автоматически при завершении программы. - Отсутствие утечек: Не используется
new.
Минусы паттерна и альтернативы:
- Глобальное состояние: Усложняет модульное тестирование, так как состояние сохраняется между тестами. Часто лучше использовать Dependency Injection, передавая зависимость явно.
- Нарушение SRP: Класс начинает отвечать и за свою бизнес-логику, и за контроль над своим экземпляром.
- Проблемы с порядком разрушения: Если синглтон зависит от другого синглтона, возможны проблемы при завершении программы.
В современных C++ проектах использование чистого Singleton часто считается антипаттерном, и предпочтение отдается другим методам управления временем жизни объектов.