++ xa lvalue 및 x ++가 rvalue 인 이유는 무엇입니까? [복제]
이 질문에 이미 답변이 있습니다.
- 접두사 증분 1 답변에 대한 lvalue 및 rvalue
나는 좌변과 우변에 최대 읽어 봤는데 내가 조금의 차이에 대해 혼란 스러워요 그래서 ++x
하고 x++
는이 분류에 온다.
++x
lvalue와 x++
rvalue 가 있는 이유는 무엇 입니까?
++x
증가한 객체에 대한 참조를 반환합니다. 여기서 as x++
는 x
의 이전 값의 임시 복사본을 반환 합니다.
적어도 이것은 관례에 따라 이러한 연산자를 구현하는 "정상적인"방법입니다. 그리고 모든 내장 유형은 이런 방식으로 작동합니다. 그리고 lvalues / rvalues에 대해 읽었다면 접두사 연산자가 명명 된 객체 자체를 반환하기 때문에 lvalue라는 것을 알 수 있습니다. .
참고 : 또한 prvalues, xvalues 등이 있으므로 요즘 기술적으로 조금 더 복잡합니다. 봐 대한 추가 정보를 원하시면 여기를.
C ++ (C와 반대)는 헌신적 인 lvalue 보존 언어입니다. 가능할 때마다 표현식의 "lvalueness"를 열심히 보존하려고 노력합니다.
사전 증가 의 "lvalueness"를 유지하는 것은 매우 쉽습니다 . 피연산자를 증가시키고이를 lvalue로 반환하기 만하면됩니다. 끝난. 반환 된 lvalue에는 포함해야하는 결과 인 피연산자의 새 (증가 된) 값이 정확히 포함됩니다.
동시에 사후 증가 의 "lvalueness"를 보존하는 것은 사실상 불가능합니다 . 정의에 따라 사후 증가의 결과는 피연산자의 이전 (원래) 값입니다. post-increment에서 lvalue를 반환하려고하면 어떻게 든 동시에 두 가지를 확인해야합니다. 1) lvalue가 증가하고, 2) 호출 코드가 동일한 lvalue (!)를 볼 때 이전 값을 확인합니다. 이러한 요구 사항의 조합은 매우 모순적이어서 기본적으로 C ++ 개체 모델에서 구현할 수 없습니다.
적절한 post-increment 동작을 구현하려면 호출 코드가 피연산자를 직접 들여다 보는 것이 아니라 호출 코드가 이전 값을 "보도록"만드는 개념적 또는 물리적 "프록시"를 살펴 봐야합니다. 피연산자의. 해당 프록시는 이전 값을 보유하는 임시 개체 일 수 있습니다. 또는 해당 프록시 는 새 값에서 빼서 즉시 이전 값을 생성하는 것일 수 있습니다
1
. 어쨌든 해당 프록시는 호출 코드가 원래 lvalue에 액세스하는 것을 방지합니다.
이것이 C ++가 쉽게 얻을 수있는 기회를 이용하여 사전 증가의 "가치성"을 보존하지만 사후 증가로 동일한 것을 달성 할 수 없음을 인정하는 이유입니다. 사후 증가의 경우 "lvalueness"를 빠르고 행복하게 버리는 경향이있는 고전적인 표준 C 동작에서 벗어나려는 노력의 가치가 없습니다.
연산자의 의사 코드로 작업을 적어두면 int
더 명확해질 수 있습니다.
접두사:
int& Prefix(int& val)
{
int& value = val;
value += 1;
return value;
}
접미사 :
int Postfix(int& val)
{
int oldValue = val;
val += 1;
return oldValue;
}
차이점은 두 연산자가 반환하는 값 (값과 참조)에 있습니다.
왜 ++ xa lvalue인가
나는 그것이 될 수 있기 때문에 lvalue라고 추측하고 있습니다.
++x
그것은 다음과 같이 생각할 수 있습니다.
((x = x + 1), x) // Increment x. Then evaluate to the value of x
또는
((x += 1), x) // Increment x. Then evaluate to the value of x
++x
lvalue 로 평가 하는 것이 합리적 입니다.
x ++ rvalue?
lvalue가 될 수 없기 때문입니다.
x++
그것은 다음과 같이 생각할 수 있습니다.
((unnamed_variable = x), (x = x + 1), unnamed_variable)
또는
((unnamed_variable = x), (x += 1), unnamed_variable)
x++
evaluates to the value of before x
is incremented. Since there is no variable that can store that value, it cannot be an lvalue.
For built-in types, such as int
, x++
yields the old value of x
. There is no storage associated with this, so it would be impossible for the expression to be an lvalue.
In C, ++x
yielded the new value of x
(and was not an lvalue). Since the object x
actually contains that same value, it is possible to have ++x
designate the object x
(i.e. be an lvalue). This is added functionality compared to yielding an rvalue, and the designer of C++ decided that this would be an improvement to the language.
For class types, it is possible overload any operator in such a way that use of the operator can yield an lvalue, xvalue, or prvalue. However it is considered good style to make overloaded operators have similar semantics to built-in operators, which is why it is normal for people to overload ++x
to yield an lvalue and to overload x++
to yield an rvalue.
First of all, an "lvalue" is an expression that is legal on the left side (the "l" in "lvalue") of an assignment. That means it represents an address whose contents can be changed by the assignment. (The C standard calls such a thing an "object".) That's why, e.g., infix operator expressions and function calls aren't lvalues.
"rvalue" is a silly term; any well-formed expression is legal on the right side of an assignment (setting aside type conversion issues).
The standard says that, e.g.:
i = ++i + 1;
a[i++] = i;
..are both "undefined statement expressions", meaning their implementation (and therefore behavior) is not standardized.
The common sense meaning of "++i" is "increment the value of the object i, and evaluate to the result". Similarly, "i++" means "evaluate to the current value of the object i, and increment the object's value afterward". Neither says what happens when "++i" or "i++" is used as an lvalue.
The standard says, about expressions: "The value computations of the operands of an operator are sequenced before the value computation of the result of the operator." This is actually ambiguous for "++i", since the value computation of the operand is affected by the value computation of the operator.
What makes the most sense to me is this:
i = 5;
++i = i + 1; /*i is set to 6*/
i++ = 1; /*i is set to 1*/
++i = ++i + 1; /*i is set to 8, but problematic*/
i++ = i++ + 1; /*i is set to 8, but problematic*/
++i = i++ + 1; /*i is set to 8, but problematic*/
My advice -- don't use expressions that are so hard to understand!
참고URL : https://stackoverflow.com/questions/50802859/why-is-x-a-lvalue-and-x-a-rvalue
'IT story' 카테고리의 다른 글
XML에서 R 데이터 프레임으로 구문 분석하는 방법 (0) | 2020.08.31 |
---|---|
Npm 루트 / 관리자로이 명령을 다시 사용하십시오. (0) | 2020.08.31 |
C ++ 상수 사용법 설명 (0) | 2020.08.31 |
부호없는 정수 빼기가 정의 된 동작입니까? (0) | 2020.08.31 |
Python에서 첫 번째 문자열 교체 (0) | 2020.08.31 |