Порядок инициализации постоянной инициализированной переменной со статической продолжительностью хранения - PullRequest
1 голос
/ 21 октября 2019

На основе следующего фрагмента кода:

const int a = 42;
const int b = a;

Мы знаем, что постоянная инициализация выполняется для обеих этих переменных, и что постоянная инициализация является статической инициализацией.

Поскольку порядок статической инициализации не определен (в отличие от динамической инициализации, в которой указан ее порядок), это может не привести к неопределенному поведению, как если бы статическая инициализация b произошла до a,это будет читать неинициализированную память?

Ответы [ 2 ]

1 голос
/ 21 октября 2019

Во-первых, давайте уточним контекст: мы рассматриваем инициализацию переменных со статической длительностью хранения. Эта инициализация фактически состоит из двух частей: статической фазы и динамической фазы. Сначала возникает статическая фаза, и между переменными на этой фазе нет никаких зависимостей. Порядок инициализации имеет значение только для динамической инициализации переменных со статическим хранилищем.

Порядок (динамической) инициализации статических переменных в целом не является неопределенным. Как правило, он не определен между отдельными единицами перевода , а также в некоторых случаях в пределах одного TU.

const int a = dynamic_init();
const int b = a;

Если эти переменные находятся в одном TU, как это может показаться из примера,затем указывается порядок: сначала объявляется a и, следовательно, сначала инициализируется.

const int a = 42;
const int b = a;

42 является константным выражением. Поэтому a имеет постоянную инициализацию, которая является статической инициализацией (не динамической). Поэтому порядок инициализации не имеет значения для этой переменной.

a также является константным выражением, поскольку a - это const переменная со статическим хранилищем и постоянным инициализатором. Поэтому b также имеет нединамическую инициализацию. Поэтому порядок инициализации не имеет значения для этой переменной.


С контекстом вне пути:

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

То, что стандарт не определяет порядок, не означает, что реализация может делать все, что угоднохочет. Стандарт говорит, что происходит статическая инициализация, и реализация отвечает за ее выполнение. Он должен выбрать порядок, который работает, как указано.

На практике порядок не имеет значения, потому что он не наблюдается для программы. Обе переменные инициализируются в 42 независимо от того, как реализация выберет для этого.

0 голосов
/ 23 октября 2019

Поскольку порядок статической инициализации не определен […], не приведет ли это к неопределенному поведению, как если бы статическая инициализация b произошла до a, это будет считывать неинициализированную память?

«Чтение памяти» (инициализировано или нет) не разрешено [conv.lval] / 2 :

Когда применяется преобразование lvalue-в-значениев выражение e, и либо- e потенциально не оценивается, или- оценка e приводит к оценке члена ex набора потенциальных результатов e, а ex называет переменную x, которая не используется odr для ex, значение, содержащееся в ссылочном объекте, недоступно .

(я думаю, мне не нужно доказывать, что a не используется odr для b 'с инициализатором)

...