작성
·
944
3
안녕하세요. 수강생입니다.
따라해 보세요에서 응용을 하다보니 다음과 같은 현상이 일어났는데 궁금해서 질문 올립니다.
코드 A : int main()
{
int a(1), b(2), c(3);
a = ++b = c;
return 0;
}
코드 B : int main()
{
int a(1), b(2), c(3);
a = b++ = c;
return 0;
}
코드 A는 모두 값이 3으로 나오나 코드 B는 작동이 되지 않습니다. (b++)을 해도 컴파일이 되지 않는데 이유가 궁금합니다!
답변 3
19
b++ = c; 식에서 발생한 컴파일 에러입니다. = 대입 연산자를 사용할 땐 = 의 왼쪽에 있는 피연산자는 반드시 L-value 여야 합니다. 위와 같이 오류 메세지에도 나와있는 것을 확인할 수 있네요! 여기서 b++ 는 L-value 가 아닌, R-value 이기 때문에 발생한 오류입니다.
✨L-value 와 R-value 의 차이
질문자님께서 질문 주신 3.1 강의 전에 L-value, R-value 에 대해서 배우셨는지 알고 계시는지 잘 모르겠어서 우선 간단히 설명 드리겠습니다. (이미 알고 계시다면 스킵해주세요!)
L-value 는 int a 이런 변수처럼 값을 저장할 수 있는 공간을 의미합니다. 공간이기 때문에 해당 공간의 어떤 유의미한 "주소"를 가집니다. a 는 L-value 이기 때문에 우리는 a = 2 이런식으로 a 에 2 를 저장할 수 있게 됩니다.
R-value 는 공간에 넣을 '값'이 됩니다. 따라서 R-value 는 L-value 처럼 어떤 값을 저장할 수 있는, 유의미한 주소를 가지는 공간이 될 수 없는니다. a = 2 에서 '2' 가 바로 R-value 가 되요! 프로그래밍 언어에서 2 = 3 는 말이 되지 않죠! 2 는 그 자체로 값이며 뭔갈 저장할 수 있는 공간으로 작용하지 않기 떄문에 2 에 3 을 저장할 수 없기 때문입니다. 그래서 R-value 는 = 대입 연산자에서 오른쪽에 오게 됩니다. 이런 2, 3 이런 리터럴 뿐만 아니라 시스템 내부에서 만들어지는 어떤 '임시 객체'도 R-value 라고 생각해주시면 됩니다.
✨b++ 가 R-value인 이유
a = b++ 라는 식이 있다면 b 가 1 증가되기 전의 값을 a 에게 넘겨주죠! b 의 초기값이 2 였다면 a 는 2 가 되고 b 는 3 이 될 것입니다. b++ 같은 후위증감연산자가 동작되는 원리는
1️⃣시스템 내부적으로 "임시 객체"가 만들어지고 이 곳에 1 증가되기 전의 기존 값을 복사해 할당합니다. 즉 b와는 별개인, b 가 1 증가되기 전의 값을 가진 "사본"이 만들어지는 것이죠. 그리고 기존 값을 가지고 있는 이 사본을 반환합니다.
2️⃣ 그리고 나서 원본인 b 를 1 증가시킵니다.
이와 같은 원리로 진행이 됩니다. 즉, b가 원래 가지고 있던 값인 2가 어떤 임시 객체에 복사되고 이 임시 객체를 반환하게 되므로 이 임시 객체가 a 에 할당되는 셈입니다. 그래서 a 가 b 의 증가되기 전의 값을 할당 받게 되는 것이에요. 원본 b 는 1 증가되구요!
따라서 "b++" 자체가 b 가 1 증가되기 전의 값을 잠시동안만 임시로 보관하는 사본인 셈입니다. 이러한 임시 객체는 시스템 내부적으로 임시적으로 b 기존값을 잠깐 동안만 보관하기 위해 만들어진 것이라서 R-value 로 취급이 됩니다. 개발자가 임의로 이 곳에 어떤 값을 저장할 수가 없기 때문입니다. 그래서 b++ = c; 는 곧 b 기존값을 임시로 보관해둔 임시객체에 c 의 값을 넣겠다는 이야기이니 컴파일 오류가 발생하게 됩니다. b++가 반환하는것은 그저 b가 1 증가되기 전의 값을 알려주기 위해 시스템이 잠시동안만 만들어 보관해둔 임시 객체일 뿐이기 때문입니다. 그래서 이에 c값을 할당할 수 없게 막아둔 것입니다.
이와 달리 ++b 전위증감 연산자는 기존값을 사본으로 만들어 이를 반환하고 뭐 이런 과정 없이 그냥 원본을 바로 1 증가시켜버리고 이 원본을 리턴하기 때문에 여전히 원본 b 그 자체입니다. 그래서 원본 b (변수니까 L-value)이기 때문에 L-value입니다. 그래서 이와 달리 ++b = c 는 문제가 없었던 것입니다. 1 증가가 완료된 b 라는 변수에 c 라는 값을 받는다는 의미가 되기 때문에 문제 없습니다.
0
0
감사합니다. 안그래도 C++ 문법을 찾아보면서 발견했는데, 이렇게 친절하게 알려주시니까 더 이해가 잘됩니다.
후위연산을 하는 순간 그 값이 l-value가 안된다는 것에 대한것과, 후위연산이 적용된 변수는 그 자체가 임시 객체가 되어 r-value가 된다는 것을 친절하게 알려주셔서 감사합니다!