Вызывает ли определение функции виртуального члена динамическую инициализацию статического члена данных в том же модуле перевода? - PullRequest
0 голосов
/ 17 сентября 2018

Рассмотрим следующие две единицы перевода:

// foo.cpp
#include <iostream>

class Foo {
public:
  virtual ~Foo() = default;

  virtual void bar();

private:
  static int _baz;
};


static int f() {
  std::cout << "f called\n";
  return 42;
}

int Foo::_baz = f();

void Foo::bar() {
  std::cout << "Baz::bar called\n";
}

и

// main.cpp
#include <iostream>
int main() {
  std::cout << "main called\n";
}

При компиляции обоих модулей перевода в один исполняемый файл (например, с помощью g++ -std=c++17 main.cpp foo.cpp, выбор уровня оптимизации или упорядочение двух файлов cpp не имеет значения), результирующий исполняемый файл печатает

f называется
основной называется

независимо от того, какой из трех основных компиляторов GCC, clang и MSVC использовался для его компиляции. Вы можете увидеть поведение для себя на wandbox .

Мой вопрос: гарантирует ли стандарт, что Foo::_baz будет инициализирован (и, следовательно, будет вызываться f) , даже если весь класс Foo не используется в программе вообще

Я считаю, что это так; мои рассуждения звучат так:

Согласно [basic.start.dynamic] / 4 , Foo::_baz не нужно инициализировать перед выполнением первого оператора main, но

если [инициализация] откладывается, то это происходит до того, как любое использование неинициализации odr любой не встроенной функции или не встроенной переменной, определенной в той же единице перевода, что и инициализируемая переменная.

Здесь "неиспользование odr-использования" определяется как

[...] использование odr ([basic.def.odr]), не вызванное прямо или косвенно инициализацией нелокальной статической переменной или переменной продолжительности хранения потока

in [basic.start.dynamic] / 3 . Но согласно [basic.def.odr] / 7 ,

функция виртуального члена используется odr, если она не является чистой.

, из которого я заключаю, что определение Foo::bar - это использование не инициализации odr-использования не встроенной функции, определенной в той же единице перевода, что и Foo::_baz, и, таким образом, Foo::_baz будет инициализировано.

Что я нахожу странным в этой строке рассуждений, так это то, что отложенная инициализация Foo::_baz должна произойти до использования odr Foo::bar, то есть до того, как будет определено Foo::bar (wtf ?!) с момента определения один - использование одр. Это заставляет меня думать, что мои рассуждения могут быть ошибочными.

Итак, еще раз: гарантирует ли стандарт, что Foo::_baz будет инициализирован (и, следовательно, будет вызываться f) , даже если ничего в его единице перевода никогда не используется в программе вообще ? Если да, есть ли что-то, что мы можем сказать о , когда это произойдет (учитывая странное ограничение порядка, которое должно произойти до того, как будет определена функция виртуального члена), и если нет, где ошибка в моих рассуждениях?

1 Ответ

0 голосов
/ 17 сентября 2018

На статическую инициализацию не влияют виртуальные функции, и связь с динамической инициализацией касается порядка, для константных инициализаторов это происходит, как указано в [class.static.data]/2

[Примечание. После определения статического члена данных он существует, даже если не создано ни одного объекта его класса. ... - конец примечания]

Однако [basic.start.dynamic]/4

Определяется реализацией, выполняется ли динамическая инициализация нелокальной не встроенной переменной со статической длительностью хранения перед первым оператором main или откладывается. Если оно откладывается, то это происходит до того, как любое использование неинициализации odr любой не встроенной функции или не встроенной переменной, определенной в той же единице перевода, что и инициализируемая переменная.

Даже если реализация решит отложить инициализацию, стандартный мандат на это произойдет. и в качестве сноски предыдущего пункта:

Нелокальная переменная со статической продолжительностью хранения, имеющая инициализацию с побочными эффектами, инициализируется в этом случае, даже если она сама по себе не используется odr.

...