Избегайте синглтонов
Причина
Синглтоны — это в основе своей сложные глобальные объекты в маскировке.
Пример
class Singleton {
// ... много всего, чтобы гарантировать создание только одного объекта Singleton,
// его правильную инициализацию и т.д.
};
Существует множество вариантов идеи синглтона. Это часть проблемы.
Примечание
Если вы не хотите, чтобы глобальный объект менялся, объявите его const или constexpr.
Исключение
Вы можете использовать простейший «синглтон» (настолько простой, что он часто не считается синглтоном) для получения инициализации при первом использовании, если это необходимо:
X& myX()
{
static X my_x {3};
return my_x;
}
Это одно из наиболее эффективных решений проблем, связанных с порядком инициализации. В многопоточной среде инициализация статического объекта не вводит состояния гонки (если только вы не получаете небрежный доступ к разделяемому объекту изнутри его конструктора).
Обратите внимание, что инициализация локального static не подразумевает состояния гонки. Однако если уничтожение X включает операцию, требующую синхронизации, мы должны использовать менее простое решение. Например:
X& myX()
{
static auto p = new X {3};
return *p; // потенциальная утечка
}
Теперь кто-то должен delete этот объект некоторым подходящим потокобезопасным способом. Это подвержено ошибкам, поэтому мы не используем эту технику, если только
myXне находится в многопоточном коде,- этот объект
Xне нужно уничтожать (например, потому что он освобождает ресурс), и - код деструктора
Xне нужно синхронизировать.
Если вы, как многие, определяете синглтон как класс, для которого создаётся только один объект, функции вроде myX не являются синглтонами, и эта полезная техника не является исключением из правила «не используйте синглтоны».
Контроль
В целом очень сложно проверить.
- Искать классы с именами, содержащими
singleton. - Искать классы, для которых создаётся только один объект (путём подсчёта объектов или изучения конструкторов).
- Если класс X имеет публичную статическую функцию, содержащую локальный статический объект типа X и возвращающую указатель или ссылку на него, запретить это.