#c++ #операторы
Содержит ли данный код UB? int i = 6; i = 7, ++i, i++;
Ответы
Ответ 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]Ответ 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. [...]Ответ 3
С чего бы это? Операция , однозначно определяет порядок (слева направо) вычисления выражений, результатом будет значение последнего выражения. У вас i станет равно 9.
Комментариев нет:
Отправить комментарий