Я только что узнал следующие факты:
Результатом приращения префикса (++ var_name) является R-значение в C (по крайней мере, я
уверен, что это не L-значение в C), но это L-значение в C ++.Результатом приращения постфикса (var_name ++) является R-значение в C (по крайней мере, я
уверен, что это не L-значение в C). Это также верно в C ++ (говорит результат
это prvalue).
Я проверил их в VS2010 (.cpp и .c) и Ubuntu (gcc и g ++).
В п.109 (5.3.2) стандарта С ++ http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf, это написано
Операнд префикса ++ изменяется путем добавления 1 или установки в значение true, если это bool (это использование не рекомендуется).
операнд должен быть изменяемым lvalue. Тип операнда должен быть арифметическим типом или указателем на
полностью определенный тип объекта. Результатом является обновленный операнд; это lvalue, а также…
и в п.101 (5.2.6)
Значением выражения postfix ++ является значение его операнда. … Результатом является
prvalue. Тип результата — cv-неквалифицированная версия типа операнда. Смотрите также 5.7 и 5.17.
(Хотя я не знаю разницы между R-значением и prvalue).
Что касается стандарта C http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf,
префикс ++ описан в 6.5.3.1, а постфикс — в 6.5.2.4, но из описания я не могу получить четкий, определенный ответ.
Я хотел бы знать причины, которые делают их R-значением или L-значением. Я знаю только то, что
We can assign a value to a (modifiable) L-value, for example, a variable name. R-value is a value of an expression.
Но я не знаю деталей, почему postfix ++ не является L-значением в C и C ++, и почему префикс ++ отсутствует в C. (Я видел что-то вроде «postfix ++ … store … во временном адресе, затем …», но я до сих пор не понимаю).
И еще один вопрос: почему префикс ++ отличается в C и C ++? Делать префикс ++ L-значением (в C ++) имеет много преимуществ? Если так, почему C не меняет это? (Другие причины, кроме обратной совместимости, или, по крайней мере, почему ее изменение вызовет много проблем).
C и C ++ — это разные языки. C ++ имеет перегрузку операторов, а C — нет. ++ операторы, будь то префикс или постфикс, являются операторами, которые могут быть перегружены в C ++. C ++ также имеет ссылки, а C — нет.
В С, ++я а также я ++ оба дают значение, которое не является именующий. Это желательно, так как в противном случае вы могли бы столкнуться с неопределенным поведением, пытаясь изменить тот же скаляр в тех же границах точки последовательности.
Пища для размышления: в Си оператор запятой также выдает значение, которое не является lvalue, поэтому «отбрасывать» lvalueness, ты можешь сделать:
(0, lvalue)
Правда, что
Оператор предварительного увеличения / уменьшения (++ var или —var) возвращает значение l (т. е. модифицируемый объект)
Оператор пост-инкремента / декремента (var ++ или var—) возвращает значение r (т. е. временный объект).
Рассмотрим следующий код с оператором предварительного увеличения / уменьшения
{
int i = 0;
int* pi = &(++i);
}
Это нормально, потому что на самом деле его псевдокод
i = i+1; // pre increment i
int* pi = &i; // then evaluate its address and assign it to pi
Теперь рассмотрим тот же код, но с оператором постинкремента / декремента и его последствиями, если он был принят компилятором.
{
int i = 0;
int* pi = &(i++); // Not OK !! because virtually it is a temporary variable
}
Его псевдокод будет
int i = 0;
int tmp = i; // compiler creates a temporary variable to save value of i
int* pi = &tmp; // then would take the address of a temporary variable
i = i + 1; // the post increment happening only after the assignment !!!
Надеюсь это поможет прояснить немного;)