Когда статическая глобальная переменная создается в С++

Я знаю, что глобальные переменные создаются в порядке объявления для той же единицы компиляции, и порядок создания не определяется между несколькими единицами компиляции.

Я прочитал некоторое время назад, что глобальные переменные создаются до того, как вызывается любой код из блока компиляции, где они определены. Определяется ли это стандартом?

Пример:

file1.cpp

int f1v1 = f1_1();
int f1v2 = f1_2();

void f1(){...}

int f1_1(){...}
int f1_2(){...}

file2.cpp

static int f2v1 = f2_1();
static int f2v2 = f2_2();

int f2_1(){...}
int f2_2(){...}

main.cpp

#include "file1.h"
#include "file2.h"

int main()
{
    f1();

    return 0;
}

В этом случае гарантируется стандартом, что f1_1() вызывается до f1_2() и до f1()? Гарантируется стандартом, что f2_1() и f2_2() вызываются вообще, поскольку не определена никакая функция, определенная в файле2.cpp, и f2v1 и f2v2 не видны вне file2.cpp?

ИЗМЕНИТЬ:

Является ли поведение, указанное стандартом при компиляции файла file1.cpp в lib1, а файл2.cpp скомпилирован в lib2?

Ответ 1

На основе [basic.start.init]:

f1_1() гарантируется выполнение до f1_2() (пункт 2: "Переменные с упорядоченной инициализацией, определенные в одной единице перевода, должны быть инициализированы в порядке их определений в блоке перевода." ).

Оба гарантированно выполняются до f1() (пункт 4: "Если инициализация отложена до некоторого момента времени после первого утверждения main, она должна произойти до первого использования odr (3.2) любой функции или переменная, определенная в той же самой единице перевода, что и переменная, подлежащая инициализации." ).

О f2_1() и f2_2(), [basic.stc.static] para.2 говорится: "Если переменная со статической продолжительностью хранения имеет инициализацию или деструктор с побочными эффектами, она не должна быть устранена, даже если она появляется быть неиспользуемым,...". Это подразумевает, что они гарантированно будут вызваны, если они содержат побочные эффекты.

Ответ 2

Если я правильно понимаю ваш вопрос, С++ гарантирует порядок инициализации переменных по порядку объявления внутри одной единицы компиляции (т.е. файл cpp). Порядок инициализации между единицами компиляции undefined.

В процессе компиляции будут вызываться функции f2_* в соответствии со стандартом, даже если функции в file2.cpp не выполняются. Но если компилятор достаточно умен, он может полностью их опустить, если он определит, что результирующая программа будет действовать так, как если бы она соответствовала стандарту. (т.е. если он может гарантировать за пределами сомнения, что не будет никакой разницы в поведении между программой и программой без вызова этих функций)