inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

홍정모의 따라하며 배우는 C++

6.15 참조와 const

const int&를 사용했을때 왜 리터럴값이 들어가도 작동하는지

820

Gretel

작성한 질문수 11

0

const int&를 사용했을때 왜 리터럴값이 들어가도 작동하는지에 대한 원리를 알 수 있을까요?

뒷쪽에서 익명객체 파트 듣다가 궁금한게 생겼는데

class mine {

private:

int value;

public:

mine(int m) :value(m) {}

int getvalue() const {

return value;

}

};

mine add(mine &m1, mine &m2) {

return mine(m1.getvalue() + m2.getvalue());

}

int main() {

cout << add(mine(5), mine(6)); 

return 0;

}

이 코드에서 add 함수 파라미터에 const를 붙이지 않으면 main에서 add함수가 작동하지 않습니다. 

 따로 mine m1(5) ,m2(6) ; 등을 만들어 add(m1,m2)를 하면 작동이 됩니다.

왜 이런일이 일어나는지에 대해 조금 혼란이 생겨서 앞 강의들을 다시 들어보다 여기까지 왔습니다. 답변 부탁드립니다

C++

답변 2

17

안소

안녕하세요!

const 레퍼런스는 L-value, R-value 모두를 참조 할 수 있으며 그냥 일반 레퍼런스는 L-value만 참조할 수 있기 때문입니다. 에러가 나신 이유는 일반 레퍼런스에 R-value를 참조하셨기 때문입니다.

혹시 L-value와 R-value 개념이 생소하실까봐 설명 드리자면 (알고 계시다면 스킵해주세요!)

L-value는 데이터를 저장할 수 있는 유의미한 메모리 공간을 의미합니다. 따라서 L-value들은 개발자가 포인터로 접근할 수 있는 "유효한 주소"를 가집니다. int a = 2; 여기서 a는 L-value입니다. 2라는 값은 a 에 저장할 수 있습니다. a는 유의미한, 데이터를 저장할 수 있는 공간인 "변수"이기 때문입니다. 따라서 L-value들은 `=` 대입 연산자에 있어서 주로 할당받는 역할을 하기 때문에 왼쪽에 오게 됩니다. int b = 2; int a = b; 이런 경우처럼 오른쪽에도 올 수 있습니다. b라는 공간 안에 있는 값을 복사하여 a라는 공간에 할당하는 의미인데 이런 경우엔 L-value도 오른쪽에 올 수 있네요. L-value는 직접 데이터를 저장할 수 있는 이름이 있는 공간이라고 생각해주시면 될 것 같아요.

R-value는 데이터를 저장할 수 없는, 시스템상 잠깐 동안만 쓰이고 버려지는 임시 공간입니다.  int a = 3; 이 표현식에서 3이 바로 R-value가 됩니다. 3 은 변수가 아니죠. 3 은 어떤 값을 집어넣어 저장할 수 있는 유의미한 공간이 아닙니다. 3이라는 것은 a에 3이라는 값을 넣어주기 위해서 아주 잠깐동안만 임시로 존재하다가 이내 사라지는 그런 이름 없는 존재입니다. 이런게 바로 R-value입니다. (함수로부터 리턴받은 값도 리턴 후 사라지는 R-value입니다.) 따라서 R-value는 절대 '=' 대입 연산자에서 왼쪽에 올 수 없습니다. 값을 할당할 수 있는 공간이 아니기 때문이죠!  3 = a; 3 = 2 이런건 있을 수 없는 표현이죠. 이런 "Hello", 323 이런 리터럴들은 전부 R-value라고 생각하시면 됩니다. 이렇게 R-value는 이름이 없는 공간, 개발자가 임의로 무언갈 저장할 수 없는 공간이며 동시에 임시적으로 잠깐 쓰이고 버려지는 공간이라고 생각해주시면 됩니다. 따라서 리터럴 뿐만 아니라 함수의 실행 결과로 리턴받은 데이터나 이름 없는 '익명 객체' 또한 R-value가 됩니다.

일반 레퍼런스는 오직 L-value만 참조할 수 있습니다. 따라서 add 함수의 매개변수는 mine & m1, mine & m2 이런 일반 레퍼런스이기에 R-value 를 파라미터로 넘길 수 없습니다. add(mine(5), mine(6)); 파라미터로  mine(5)와 mine(6)을 넘기셨는데 이것들은 R-value입니다. 이름이 없는 익명객체이기 때문입니다. (익명 객체는 8.13 강의에서 자세히 배우시게 됩니다.)

mine m1(5) ,m2(6) ; 이렇게 m1과 m2이라는 이름으로 접근할 수 있게 됐기 때문에 여기서 m1과 m2는 L-value입니다. m1과 m2라는 이름으로 접근할 수 있으며 이 메모리의 값을 수정하고 다른 값을 집어넣어 저장할 수도 있어요. 객체의 이름이 m1과 m2인 것이죠! add(m1,m2) 는 L-value를 넘기셨던것이니 작동이 잘 되었던 것입니다.

그러나 그냥 mine(5) 와 mine(6) 은 위와 같은 m1, m2 이런 이름 없이 생성된 객체나 마찬가지입니다. 이렇게 익명으로 객체를 생성하시면 이 객체는 어떤 이름을 가지는 메모리가 아니기에 개발자가 임의로 다른 값을 집어넣거나 할 수 있는 유의미한 공간이 아니게 됩니다. 따라서 add(mine(5), mine(6)); 이렇게 파라미터를 넘기시면 R-value 를 넘긴 것이니 일반 레퍼런스인 mine& m1과 mine& m2이 이를 참조할 수 없어 컴파일 에러가 발생하셨던 것입니다. 마치  int & a = 2 이렇게 쓰신것과 마찬가지에요.

const 레퍼런스는 L-value와 R-value 둘 다 참조할 수 있기에 const를 붙이면 add(mine(5), mine(6)); 이렇게 익명 객체(R-value)를 파라미터로 넘겨도 잘 작동했던 것입니다. 

일반 레퍼런스가 R-value를 참조할 수 없는 이유는, 직관적으로 생각해보시면 int & a = 2 이게 가능한 표현식이 된다고 가정해보면 a는 2의 별명이 되므로 a = 5 이 식은 즉 2 = 5 와도 같아지고 이게 가능해진다는 것인데.. 이건 말이 되지 않죠!  2는 어떤 값을 저장할 수 있는 유의미한 이름있는 공간이 아니기 떄문입니다. 따라서 일반 레퍼런스는 R-value를 참조할 수 없도록 문법적으로 막혀있는 것입니다.

반면 const레퍼런스가 R-value 또한 참조할 수 있는 이유는, const int & a = 2; 라는 표현식은 a가 2라는 임시 공간의 별명이 된다는 것인데 const가 붙었으므로 이 2라는 공간을 수정하거나 어떤 값을 넣어주려는 행위는 어차피 불가능하죠! const가 붙었기때문에 어차피 a = 3 이런 수정이 불가능하기 때문에 가능한 것입니다. 이렇게 const레퍼런스가 R-value를 참조하게 되면 수정은 불가하고 오직 "접근" 만 가능하도록 보장해주는 것이니 문제없습니다. 이 2라는 임시 공간을 set은 못하고 get만 할 수 있도록 보장되니 가능한 것이에요. 

도움이 되셨으면 좋겠습니다. 

0

it09kim

감사합니다

0

Gretel

자세한 답변 너무 감사드립니다. r밸류와 l밸류를 제대로 이해했고 그에 따른 const 의 역할 또한 한번 더 짚게됐습니다. 감사합니다!!!

변수가 메모리에 저장되는 것을 알려주는 강의가 어떤강의였죠

1

463

1

메모리 주소 10진수로 출력

1

651

1

클래스 템플릿 특수화에서 boolalpha로 표현된 리턴값에 대해 질문이 있습니다.

1

496

1

여러가지 리턴 타입에 관한 강의가 어떤 걸까요?

1

532

1

메모리 주소에 관한 질분

0

677

1

인터페이스 클래스에서 reportError의 매개변수에 대해 궁금한 것이 있습니다.

0

547

1

형변환 오버로딩에서 const 관련 질문이 있습니다.

0

442

1

Digit 뒤에 reference를 사용하는 이유

0

507

1

4.2 전역 변수, 정적 변수, 내부 연결, 외부 연결

0

320

1

dat파일이...

0

537

1

TODO:대입 연산자 오버로딩에 대한 소스코드입니다.

0

641

1

복사 생성자 관련 질문이 있습니다.

0

453

1

수업 중 궁금한점이 있습니다.

1

388

1

라이브러리자체가 이해가 되지 않습니다.

0

559

1

마지막 예제 질문

0

301

1

증감연산자 위치에 따른 수행 순서 질문입니다.

0

373

1

단항 연산자 오버로딩에서 return 부분에 질문이 있습니다.

1

409

1

friend함수 관련 질문이 있습니다.

0

310

1

operator+ 정의부분에서 궁금한 것이 있습니다.

0

446

1

3분 17초 질문

0

349

1

함수에 값을 대입한다는 개념이 이해가 되지 않습니다.

0

445

1

int getvalue() const에서 const는 왜 뒤에 붙는건가요?

0

440

2

const Something &st에서 const를 빼면 안되나요?

0

299

1

friend함수는 다른 클래스의 멤버함수로 쓸 수 없나요??

1

490

1