Содержит ли данный код UB?
int i = 6;
i = 7, ++i, i++;
Такие операторы, как оператор запятая, оператор логического И (&&) и оператор логического ИЛИ (||) перед вычислением следующего операнда выполняют все побочные эффекты, связанные с выражением для первого операнда.
Например, вы можете написать
std::cout << ( i++, i++, i++ ) << std::endl;
или
if ( i++ > 0 && i++ < 10 ) { /* ... */ }
или
if ( i++ == 0 || i++ % 3 == 0 ) { /* ... */ }
То же самое относится к спискам инициализации в C++. Например,
int a[] = { i++, ++i };
Или в конструкторе класса
struct A
{
int x;
int y;
A( int i ) : x( i++ ), y( ++i )
{
//,,,
}
};
Если поведение перечисленных операторов относительно побочных эффектов одинаково и в C++, и в C, то относительно списков инициализации между этими двумя языками имеется важное отличие. В C порядок вычисления побочных эффектов инициализаторов в списке инициализации не определен.
Из стандарта C (6.7.9 Initialization)
23 The evaluations of the initialization list expressions are indeterminately sequenced with respect to one another and thus the order in which any side effects occur is unspecified.152
Сравните эту цитату с цитатой из стандарта C++ (8.5.4 List-initialization)
4 Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (14.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list. [Note: Thisevaluationorderingholdsregardlessofthesemanticsoftheinitialization; forexample, itapplies when the elements of the initializer-list are interpreted as arguments of a constructor call, even though ordinarily there are no sequencing constraints on the arguments of a call. —end note]
Нет, никакого UB тут нет, если учесть, что группировка операторов и операндов в этом выражении имеет следующий вид
(i = 7), (++i), (i++);
Оператор "запятая" упорядочивает (sequences) как вычисление значений своих операндов, так и выполнение их побочных эффектов. (Выражаясь старой терминологией, оператор "запятая" является точкой следования).
Сначала будет вычисляться левый операнд, а затем - правый. Причем все побочные эффекты вычисления левого операнда возымеют место еще до того, как начнется вычисление правого операнда.
5.19 Comma operator [expr.comma]
1 [...] A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-value expression. Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. [...]
С чего бы это?
Операция ,
однозначно определяет порядок (слева направо) вычисления выражений, результатом будет значение последнего выражения.
У вас i
станет равно 9.
Задача: параллельно читать файлы и выводить в консоль имя файла и цифру из файла
Имеется такая учебная задача:
Допустим, дано расписание автобусов на какой-то день, в виде списка числовых значенийОпределить ближайший к текущему времени автобус