Мне придется пойти так далеко, чтобы сказать, что это плохая форма для не POD, особенно если вы работаете в команде в основном из-за проблем порядка инициализации, которые могут легко возникнуть из-за этого.
// the following invokes undefined behavior.
static bool success=cout<<"hello world\n";
Люди, как правило, не пишут код, подобный описанному выше, но учитывают, был ли успех инициализирован возвращаемым значением другой функции. Теперь любой, кто испытывает желание использовать cout, cerr или любой другой глобальный объект в этой функции, вызывает то же неопределенное поведение.
Для пользовательских типов с конструкторами и деструкторами рассмотрим альтернативный метод, где доступ - это инициализация:
static Foo& safe_static()
{
static Foo f;
return f;
}
К сожалению, это также имеет проблемы с безопасностью потоков, поэтому для построения 'f' необходим некоторый механизм блокировки, если вы обращаетесь к safe_static одновременно.
Тем не менее, я думаю, что нужно стараться сделать вещи простыми. К сожалению, когда дело доходит до пользовательских объектов, определенных в области видимости файла, слишком легко столкнуться с неопределенным поведением. Небольшое дополнительное усилие, необходимое для написания чего-то вроде safe_static выше, может предотвратить много головной боли.
Исключения составляют еще один момент. Если ваши статические объекты выбрасывают из своего конструктора, то у вас нет возможности перехватить исключение. Если вы хотите, чтобы ваше приложение было действительно устойчивым и даже обрабатывало ошибки запуска, вам придется тщательно структурировать свой код (например: иметь блоки try / catch в конструкторах для объектов, которые вы создаете в области видимости файла, чтобы исключение не создавалось) за пределами ctor, а также избегайте списков инициализаторов, которые выбрасывают).
Если вы работаете в команде, вы можете подумать: «О, у меня нет доступа к другим глобальным объектам в моем классе, я мог бы также сделать его простым глобальным с внутренней связью в области видимости файла». Тогда это может быть правдой, но, прежде чем вы это узнаете, ваш коллега добавляет еще одну глобальную переменную и пытается получить к ней доступ из конструктора вашего класса. Внезапно у вас возникает неопределенное поведение, которое может даже не проявиться в качестве проблемы на основной платформе, на которую вы ориентируетесь только для сбоя вашего кода и выполнения других странных действий при попытке перенести код в другое место.
Это действительно не стоит потенциальной головной боли IMO, и эту проблему гораздо проще избежать, чем исправить.