Содержит ли данный код UB?

285
21 января 2017, 11:43

Содержит ли данный код UB?

int i = 6;
i = 7, ++i, i++;
Answer 1

Такие операторы, как оператор запятая, оператор логического И (&&) и оператор логического ИЛИ (||) перед вычислением следующего операнда выполняют все побочные эффекты, связанные с выражением для первого операнда.

Например, вы можете написать

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]

Answer 2

Нет, никакого 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. [...]

Answer 3

С чего бы это?

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

У вас i станет равно 9.

READ ALSO
Работа с потоками boost

Работа с потоками boost

Задача: параллельно читать файлы и выводить в консоль имя файла и цифру из файла

317
Поиск ближайшего значения в массиве

Поиск ближайшего значения в массиве

Допустим, дано расписание автобусов на какой-то день, в виде списка числовых значенийОпределить ближайший к текущему времени автобус

285