Локальная статическая переменная внутри функции сохраняет значение между вызовами. Это свойство иногда используют чтобы «исправить» висящие указатели или ссылки: вместо возвращения или хранения ссылки на временный объект создают static объект, который живёт долго. Такое решение меняет проблему времени жизни, но не устраняет её корень и может ввести новые ошибки.
Как появляется общее состояние
Типичная ситуация: контроллер виджета хранит указатель или ссылку на структуру параметров, созданную в вызывающей функции. После выхода из функции временная структура уничтожается, а у контроллера остаётся висящий указатель. Перевод структуры в static продлевает её существование, но при этом все последующие вызовы функции будут возвращать или ссылаться на один и тот же объект — тот самый static, инициализированный при первом обращении.
Если при каждом вызове присваивать новым данным поля этого единственного объекта, то параметры всех виджетов, которые ссылаются на этот объект, будут изменяться одновременно. Таким образом попытка «исправить» владение фактически превращает независимые объекты в зависимые от общего состояния. При конкурентном доступе добавляется риск гонок данных: хотя инициализация local static в современных компиляторах потокобезопасна, последующие записи в общий объект не становятся автоматически безопасными.
Что следует явно выразить в интерфейсе
Правильный подход — явно определить владение и время жизни. Если данные небольшие и независимы, контроллер должен хранить собственную копию. Если требуется совместное использование и разделяемое владение, используйте механизмы, отражающие это в типах: std::shared_ptr или другие владенческие примитивы. В случаях, когда нужно создавать разделяемый объект на основе существующего значения, пригодится aliasing-конструктор std::shared_ptr, позволяющий разделять владение при сохранении нужного представления объекта.
Ключевые принципы:
- Не продлевайте время жизни временного объекта неявно через static, если нужен независимый объект для каждого вызова.
- Выражайте владение в сигнатурах и типах: копия, уникальное владение или разделяемое владение должны быть очевидны потребителю API.
- При совместном доступе учитывайте вопросы синхронизации: потокобезопасная инициализация static не снимает ответственность за защиту последующих изменений.
Итого: local static меняет продолжительность жизни объекта, но не делает интерфейс правильным — он может скрыть ошибку владения и создать нежелательные общие состояния. Лучше явно продумать, кто владеет данными и как долго они должны жить, и выбрать соответствующие типы и механизмы синхронизации.