Заказ в инициализации в C, С++
Рассмотрим следующие инициализации:
/* C, C++ */
int a[] = { f(), g() };
struct { int x, y } foo = { f(), g() };
/* C++ */
struct goo { goo(int x, int y); };
goo b = { f(), g() };
goo c { f(), g() }; /* C++11 */
goo d ( f(), g() );
Является ли порядок выполнения f()
и g()
в любой строке, заданной стандартами C и С++?
Ответы
Ответ 1
Во всех этих двух случаях
goo b = { f(), g() };
goo c { f(), g() }; /* C++11 */
порядок оценки определяется слева направо, и все побочные эффекты должны применяться перед следующим инициализатором.
Из С++ STandard
4 В списке инициализаторов списка с привязкой-инициализацией инициализатор-предложения, в том числе любые из результатов расширения пакета (14.5.3), оцениваются в том порядке, в котором они появляются. То есть, вычисление каждого значения и побочный эффект, связанный с данным Параметр инициализатор секвенирован перед каждым вычислением значения и побочный эффект, связанный с любым предложением инициализатора, которое следует за ним в список списков инициализаторов, разделенных запятыми.
Однако в C существует другое правило
Оценки выражений списка инициализации неопределенно упорядочены по отношению друг к другу и, следовательно, порядок, в котором происходят какие-либо побочные эффекты, не указывается.
Ответ 2
Является ли порядок выполнения f() и g() в любой строке, заданной стандартами C и С++?
В C, Нет. Они могут оцениваться в любом порядке.
C11 6.7.9 Инициализация
Оценки выражений списка инициализации неопределенно упорядочены с помощью друг другу и, следовательно, порядок, в котором происходят какие-либо побочные эффекты, не определено, 152).
В то время как С++ 11 говорит, что порядок оценки детерминирован.
8.5.4: 4 List-initialization
В списке инициализаторов списка с привязкой к инициализации предложения инициализатора, включая все, которые являются результатом разложений пакетов (14.5.3), , оцениваются в том порядке, в котором они отображаются, То есть, каждое вычисление значения и побочный эффект, связанный с заданным предложением инициализатора, секвенируются перед вычислением каждого значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в разделенном запятыми списке списка инициализаторов.
152) В частности, порядок оценки не обязательно должен совпадать с порядком инициализации субобъекта.
Ответ 3
Нет, в C порядок оценки инициализаторов не указан:
(C11, 6.7.9p23) "Оценки выражений списка инициализации неопределенно секвенированы относительно друг друга и, следовательно, порядок, в котором происходят любые побочные эффекты, unspecified.152)"
152) В частности, порядок оценки не должен совпадать с порядком инициализации субобъекта.
В С++ поведение отличается, а инициализаторы оцениваются в том порядке, в котором они отображаются (С++ 11, 8.5.4p4).
Ответ 4
В С++ 11 соответствующая часть - это абзац 4 8.5.4 Инициализация списка
В списке инициализаторов списка с привязкой к инициализации предложения инициализатора, включая все, которые являются результатом разложений пакетов (14.5.3), , оцениваются в том порядке, в котором они отображаются, То есть, каждое вычисление значения и побочный эффект, связанный с заданным предложением инициализатора, секвенируются перед вычислением каждого значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в разделенном запятыми списке списка инициализаторов. [Примечание. Это упорядочение оценки выполняется независимо от семантики инициализации; например, он применяется, когда элементы списка инициализатора интерпретируются как аргументы вызова конструктора, хотя обычно нет ограничений последовательности для аргументов вызова. - конечная нота]
Таким образом, порядок оценки слева направо.
Однако отметим, что, к сожалению, из-за bug, поскольку по крайней мере версия 4.7.0, GCC оценивает в обратном порядке, справа налево. Поэтому, если вы получите неожиданные результаты, это может быть причиной.