레퍼런스 관련 질문입니다.
안녕하세요
class Calc
{
private:
int m_value;
public:
Calc(int init_value)
: m_value(init_value)
{}
Calc& add(int value) { m_value += value; return *this; }
Calc& sub(int value) { m_value -= value; return *this; }
Calc& mult(int value) { m_value *= value; return *this; }
Calc& div(int value) { m_value /= value; return *this; }
void print()
{
cout << m_value << endl;
}
};
int main()
{
//Simple s1(1), s2(2);
//s1.setID(2);
//s2.setID(4);
//cout << &s1 << " " << &s2 << endl;
Calc cal(10);
cal.add(10).sub(1).mult(2).print();
//cal.add(10);
//cal.sub(1);
//cal.mult(2);
//cal.print();
Calc &temp1 = cal.add(10);
cout << &temp1 << endl;
temp1.print();
Calc &temp2 = temp1.sub(1);
cout << &temp2 << endl;
temp2.print();
Calc &temp3 = temp2.mult(2);
cout << &temp3 << endl;
temp3.print();
위에 코드가 원본 코드입니다.
저기서
Calc 함수 생성자 내에 add,sub,mult 함수의 리턴값을
레퍼런스가 아닌 그냥 Calc로
public:
Calc(int init_value)
: m_value(init_value)
{}
Calc add(int value) { m_value += value; return *this; }
Calc sub(int value) { m_value -= value; return *this; }
Calc mult(int value) { m_value *= value; return *this; }
Calc div(int value) { m_value /= value; return *this; }
질문
이렇게 받았을때 리턴값이 Main 내에 Calc temp1 = cal.add(10);
했을 때 38에서 +10이 되어서 48이 되어야 할 것 같은데 30이 나오는데 그 이유가 궁금합니다.
그뒤에는 -1 *2 된 값이 나와서
이전 값이 30이라고 가정한다면 때 각 각
Calc temp2 = temp1.sub(1);
Calc temp3 = temp2.mult(2); 의 리턴 값으로 29, 58로 나옵니다.
유튜브로 실리콘밸리에서 생활하시는 영상 잘 보고 있습니다 바쁘신 와중에도 답변 해주셔서 감사합니다.
답변 1
10
강의 코드대로 참조로 했을 때, 질문자님처럼 참조 다 떼고 값으로 했을 때의 과정을 적어보겠습니다. 한번 비교해보세요!
& 참조일 때
Calc cal(10);
cal.add(10).sub(1).mult(2).print();
cal 객체 -> m_value = 10
cal.add(10) 로 인하여 cal 객체의 m_value 가 20 이 된 후 이 cal 객체 "원본"을 리턴 (즉, 원본 참조)
연쇄 호출 : 리턴된 cal 객체 "원본"에서 sub(1) 호출로 인하여 cal 객체의 m_value 가 19 이 된 후 이 cal 객체 "원본"을 리턴 (즉, 원본 참조)
연쇄 호출 : 리턴된 cal 객체 "원본"에서 mult(2) 호출로 인하여 cal 객체의 m_value 가 38 이 된 후 이 cal 객체 "원본"을 리턴 (즉, 원본 참조)
연쇄 호출 : 리턴된 cal 객체 "원본"에서 print() 호출로 인하여 cal 객체의 m_value 인 38 출력
Calc& temp1 = cal.add(10);
temp1 은 Calc& 참조타입입니다. 그러니 cal.add 가 리턴하는 객체 (*this 이니 cal 객체 본인이죠) 그 자체를 참조하게 됩니다. 즉, temp1 과 cal 은 동일한 객체를 가리키게 됩니다. (m_value 가 38이 된 그 객체) 즉 temp1 은 곧 cal 이나 마찬가지인거에요. 그러니 temp1.sub(1) 은 곧 cal.sub(1) 이나 마찬가지이고, temp2.mult(2) 도 곧 cal.mult(2) 나 마찬가지이게 된 것입니다. temp1,2,3 이 cal 객체 그 자체를 "참조" 하던 것을 생각해보면 왜 48 47 97 가 출력됏는지 이해하실 겁니다.
참조 아닐 때
Calc cal(10);
cal.add(10).sub(1).mult(2).print();
cal 객체 -> m_value = 10
cal.add(10) 로 인하여 cal 객체의 m_value 가 20 이 된 후 이 cal 객체를 복사한 "사본"을 리턴 (그냥 Calc 리턴 타입이기 때문에 이는 *this 를 리턴한거더라도 cal 원본 그 자체의 참조가 아닌 cal 의 사본인 임시 객체를 리턴하는 것입니다.)
연쇄 호출 : 리턴된 m_value = 20 상태의 "임시 객체"에서 sub(1) 호출로 인하여 "임시 객체"의 m_value 가 19 이 된 후 이 임시 객체를 복사한 "사본"을 리턴 (원본인 cal 객체는 m_value = 20 상태에서 더 이상 변하지 않았습니다. 빼기 1 이 된건 사본 임시 객체의 m_value 일 뿐입니다.)
연쇄 호출 : 리턴된 m_value = 19 상태의 "임시 객체"에서 mult(2) 호출로 인하여 "임시 객체"의 m_value 가 38 이 된 후 이 임시 객체를 복사한 "사본"을 리턴 (원본인 cal 객체는 m_value = 20 상태에서 더 이상 변하지 않았습니다. 곱하기 2 가 된건 사본 임시 객체의 m_value 일 뿐입니다.)
연쇄 호출 : 리턴된 m_value = 38 상태의 "임시 객체"에서 print() 호출로 인하여 "임시 객체"의 m_value (38) 가 출력됨
즉, 여기까지 과정으로 38이 출력되게 되었으나, 원본인 calc 은 원본에서 호출한 cal.add(10) 에서 변경된 m_value = 20 상태에선 변함이 없습니다. 즉, 원본은 20 인거에요. sub(1).mult(2).print() 는 사본인 임시객체에서 호출된거구요!
Calc temp1 = cal.add(10);
이 과정은 cal.add(10) 가 리턴한 임시 객체를 복사하여 temp1 이 담게 된 경우입니다. temp1 은 그냥 Calc 타입의 변수일 뿐입니다. 즉, 앞에서 참조 붙였을 때와는 다르게 temp1 과 cal 은 전혀 다른 별개의 객체가 되는 것입니다. (복사만 된 사본) cal 의 m_value 는 20 이라고 말씀드렸습니다. 그러니 add(10) 으로 30이 된 후 temp1 은 이 m_value 가 30이 된 모습의 cal 객체의 사본이 되므로 30을 출력하는 것입니다.
temp2 는 m_value 가 30 인 temp1 에서 호출한 sub(1) 리턴 객체의 사본이니 29 가 되는 것이구요
마찬가지로 temp3 은 m_value 가 58 인 temp2 에서 호출한 mult(2) 리턴 객체의 사본이니 58 이 되는 것입니다.
질문자님의 코드일 땐 참조를 사용한 강의 코드와는 다르게 cal, temp1, temp2, temp3 전부 다 별개의 존재들이라는 것을 기억하셔야 합니다.
-
참조에 대한 개념이 자리 잡혀 있어야 이해를 하실 수 있는 부분이라 앞 부분에서 배우셨을 참조 부분을 다시 참고 해보시기를 추천드립니다!
변수가 메모리에 저장되는 것을 알려주는 강의가 어떤강의였죠
1
481
1
메모리 주소 10진수로 출력
1
672
1
클래스 템플릿 특수화에서 boolalpha로 표현된 리턴값에 대해 질문이 있습니다.
1
515
1
여러가지 리턴 타입에 관한 강의가 어떤 걸까요?
1
549
1
메모리 주소에 관한 질분
0
687
1
인터페이스 클래스에서 reportError의 매개변수에 대해 궁금한 것이 있습니다.
0
558
1
형변환 오버로딩에서 const 관련 질문이 있습니다.
0
448
1
Digit 뒤에 reference를 사용하는 이유
0
512
1
4.2 전역 변수, 정적 변수, 내부 연결, 외부 연결
0
325
1
dat파일이...
0
540
1
TODO:대입 연산자 오버로딩에 대한 소스코드입니다.
0
651
1
복사 생성자 관련 질문이 있습니다.
0
456
1
수업 중 궁금한점이 있습니다.
1
392
1
라이브러리자체가 이해가 되지 않습니다.
0
565
1
마지막 예제 질문
0
305
1
증감연산자 위치에 따른 수행 순서 질문입니다.
0
382
1
단항 연산자 오버로딩에서 return 부분에 질문이 있습니다.
1
416
1
friend함수 관련 질문이 있습니다.
0
313
1
operator+ 정의부분에서 궁금한 것이 있습니다.
0
448
1
3분 17초 질문
0
354
1
함수에 값을 대입한다는 개념이 이해가 되지 않습니다.
0
450
1
int getvalue() const에서 const는 왜 뒤에 붙는건가요?
0
453
2
const Something &st에서 const를 빼면 안되나요?
0
304
1
friend함수는 다른 클래스의 멤버함수로 쓸 수 없나요??
1
495
1





