Рассмотрим код:
int i, j;
i = (i = 1, j = 3);
i++;
cout<<i<<" "<<j;
Это напечатано 4 3
(C ++ 14).
Я прочитал, что оператор запятой вычисляет выражение слева и возвращает его справа. Теперь, если это правильно, я хочу знать, каково возвращаемое значение j = 3? Это значение? Или ссылка на lvalue?
Как это на самом деле работает?
Я хочу знать, что является возвращаемым значением J = 3?
Операции присваивания * возвращают (или «оценивают») ссылку на левую часть операции, в данном случае j
,
Так i = (i = 1, j = 3);
идентичен:
i = 1;
j = 3;
i = j;
* Для встроенных типов это. изготовленный на заказ operator=
перегрузки могут возвращать все, что они хотят, хотя рекомендуется возвращать ссылку на *this
как это ожидаемое поведение среди программистов C ++.
Чтобы вычислить (i = 1, j = 3), он вычисляет слева направо выражения, разделенные запятой, и возвращает значение последнего (крайнего правого) выражения. Таким образом, он вычисляет i = 1 (i становится 1), затем он вычисляет j = 3 (j становится 3), а затем возвращает 3.
После вычисления (i = 1, j = 3), которое вернуло 3, оно выполняет присваивание, которое устанавливает для i значение 3.
Затем вычисляется i ++, что устанавливает i в 4.
Затем я и J печатаются.
Оператор присваивания возвращает значение l, ссылающееся на левый операнд. Он группируется справа налево. ([Expr.ass]). Обратите внимание, что возвращение ссылки на lvalue не имеет смысла — оно либо возвращает lvalue, либо нет.
Оператор запятой выполняет вычисления значения и побочные эффекты от левого операнда, отбрасывает их, а затем делает то же самое для правого операнда. ([Expr.comma])
Поэтому рефакторинг оператора запятой приведет к следующему эквивалентному коду:
i = 1; // left operand, value discarded
i = j = 3; // right operand, value preserved
i++;
и затем рефакторинг составного присваивания даст следующий все еще эквивалентный код:
i = 1;
j = 3; // rightmost assignment
i = j; // leftmost assignment
i++;