Я думаю, что в этом примере отсутствует то, как избежать создания Stream, это часто непереносимо. Помимо изящного счетчика, роль инициализатора заключается в создании чего-то вроде:
extern Stream in;
Если одна единица компиляции имеет память, связанную с этим объектом, есть ли какой-то специальный конструктор перед использованием нового оператора на месте, или в случаях, которые я видел, память выделялась другим способом, чтобы избежать конфликтов , Мне кажется, что если в этом потоке есть конструктор без операции, то порядок того, вызывается ли инициализатор первым или конструктор без операции, не определен.
Для выделения области байтов часто непереносимо, например, для gnu iostream пространство для cin определяется как:
typedef char fake_istream[sizeof(istream)] __attribute__ ((aligned(__alignof__(istream))))
...
fake_istream cin;
llvm использует:
_ALIGNAS_TYPE (__stdinbuf<char> ) static char __cin [sizeof(__stdinbuf <char>)];
Оба делают определенные предположения о пространстве, необходимом для объекта. Где счетчик Шварц инициализируется с новым размещением:
new (&cin) istream(&buf)
Практически это не выглядит так портативно.
Я заметил, что некоторые компиляторы, такие как gnu, microsoft и AIX, имеют расширения компилятора, влияющие на порядок статического инициализатора: