Рекурсивная зависимость переменной и функции в глобальной области видимости - PullRequest
4 голосов
/ 16 апреля 2020

Я играл с моим компилятором C ++ и заметил рекурсивную зависимость глобальной переменной, и вызов функции не отклоняется. Пример:

#include <iostream>

int foo();

int t = foo();

int foo()
{
    std::cout << "Hello before main: " << t << "\n";
    t = 10;
    return t + 10;
}

int main()
{
  std::cout << "Hello from main.\n";
}

Эта скомпилированная программа распечатывает следующее:

Hello before main: 0
Hello from main.

Поэтому, когда я использую объявление t, оно зависит от функции foo, которая снова имеет зависимость от t. Компилятор C ++ разбивает этот l oop, по существу, t инициализируется нулями до выполнения выражения присваивания.

Это меня удивило. Это правильное поведение в соответствии со стандартом или я вызываю здесь какое-то неопределенное поведение?

1 Ответ

4 голосов
/ 16 апреля 2020

Поскольку C ++ 20 , считается, что время жизни объекта начинается, когда завершаются его инициализации; до этого доступ к нему приводит к UB.

[basi c .life] / 1 :

... Время жизни объекта тип T начинается, когда:

  • хранилище с правильным выравниванием и размером для типа T получено, и
  • его инициализация (если есть) завершена (включая пустую инициализацию ) ...

До C ++ 20 это было четко определенное поведение. Нулевая инициализация выполняется сначала для нелокальных переменных .

Как описано в нелокальной инициализации , stati c и локальные переменные потока that aren't constant-initialized (since C++14) инициализируются нулями перед любой другой инициализацией. Если определение нелокальной нелокальной переменной не имеет инициализатора, то инициализация по умолчанию ничего не делает, оставляя неизменным результат предыдущей инициализации нуля.

Из стандарта [ basi c .start.static] / 2

Если постоянная инициализация не выполняется, переменная со значением stati c длительности хранения ( [basi c .st c .static] ) или длительность хранения потока ( [basi c .st c .thread] ) инициализируется нулями ( [dcl.init] ). Вместе нулевая инициализация и постоянная инициализация называются stati c initialization; все остальные инициализации - это инициализация Dynami c. Вся инициализация stati c происходит до ( [intro.races] ) любой динамической инициализации c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...