Изящный счетчик / счетчик Шварца, совместимый со стандартами?

Сегодня утром я обсуждал с коллегой порядок инициализации статических переменных. Он упомянул счетчик Nifty / Schwarz , и я (вроде) озадачен. Я понимаю, как это работает, но не уверен, что это технически соответствует стандарту.

Предположим, что следующие 3 файла (первые два скопированы из More C ++ Idioms ):


//Stream.hpp
class StreamInitializer;

class Stream {
   friend class StreamInitializer;
 public:
   Stream () {
   // Constructor must be called before use.
   }
};
static class StreamInitializer {
  public:
    StreamInitializer ();
    ~StreamInitializer ();
} initializer; //Note object here in the header.

//Stream.cpp
static int nifty_counter = 0; 
// The counter is initialized at load-time i.e.,
// before any of the static objects are initialized.
StreamInitializer::StreamInitializer ()
{
  if (0 == nifty_counter++)
  {
    // Initialize Stream object's static members.
  }
}
StreamInitializer::~StreamInitializer ()
{
  if (0 == --nifty_counter)
  {
    // Clean-up.
  }
}

// Program.cpp
#include "Stream.hpp" // initializer increments "nifty_counter" from 0 to 1.

// Rest of code...
int main ( int, char ** ) { ... }

... и вот в чем проблема! Есть две статические переменные:

  1. "nifty_counter" в Stream.cpp ; и
  2. «инициализатор» в Program.cpp .

Поскольку две переменные находятся в двух разных модулях компиляции, нет (AFAIK) официальных гарантий, что nifty_counter инициализируется значением 0 до вызова конструктора initializer .

Я могу думать о двух быстрых решениях как о двух, почему это «работает»:

  1. современные компиляторы достаточно умны, чтобы разрешить зависимость между двумя переменными и разместить код в соответствующем порядке в исполняемом файле (что очень маловероятно);
  2. nifty_counter фактически инициализируется во время загрузки, например в статье говорится, что его значение уже помещено в «сегмент данных» в исполняемом файле, поэтому он всегда инициализируется «перед запуском любого кода» (весьма вероятно).

Мне кажется, что оба они зависят от какая-то неофициальная, но возможная реализация. Соответствует ли этот стандарт или он «настолько вероятно сработает», что нам не стоит беспокоиться об этом?

16
задан jww 23 March 2017 в 23:32
поделиться