작성
·
146
0
은닉성 강의 22분대에서
int GetHp() { return _hp; }
void SetHp(int hp)
{
_hp = hp;
if (_hp <= 50)
{
SetBerserkerMode();
}
}
캡슐화를 설명하시면서 이런 함수가 등장합니다
여기서 위 함수를
int& GetHp() { return _hp; }
void SetHp(int& hp)
{
_hp = hp;
if (_hp <= 50)
{
SetBerserkerMode();
}
}
이런식으로 참조로 받으면 안되나요?(-> 만약에 변수가 여러개여서 복사 대입에 연산이 많이 필요하다는 가정하에서요)
앞선 강의에서 함수의 스택프레임이 해제될 때 반환형으로 참조형이나 포인터를 넘겨주게 되면 문제가 발생할 수 있다고 하셨습니다.
(엉뚱한 주소를 가리킬 수 있으므로 함수나 변수가 생존 범위를 넘어서 해제 될 때 그 변수의 참조나 포인터를 넘기지 말라고 하셨 습니다.)
위의 경우도 그 조심하라고 하셨던 경우랑 똑같은 건가요?
아니면 this가 생략되어 있지만 자기자신이 들어갔다 나오므로 참조로 값을 받고 참조를 반환해도 괜찮은 건가요?
답변 2
1
int& Get()
{
int a = 0;
return a;
}
위와 같이 함수 내부에서 사용하는 로컬 변수의 참조값을 반환하는 것은
스택의 영역이 함수가 끝나면 스택 영역은 유효하지 않기 때문에 문제가 있습니다.
반면 클래스 멤버 함수에서 멤버 변수의 참조값을 반환하는 것은
(설계적인 문제를 따지지 않고) 안정성 자체만 놓고 보면 '당장' 문제는 없습니다.
'당장'이라 하는 이유는 혹시라도 나중에라도 delete 등으로 객체 자체를 메모리에서 날리면
역시나 해당 주소는 유효하지 않게 되므로 문제가 될 수는 있기 때문입니다.
물론 그 경우는 엄밀히 말해 int& GetHp() { return _hp; } 자체의 문제라기 보다는
저렇게 참조값을 갖고 온 다음에, 객체를 삭제한 쪽의 잘못도 반은 있죠.
만약 객체가 힙이 아닌 스택에 올라간 상태라고 하면,
역시나 해당 참조 주소를 함수 외부로만 건내주지 않으면 문제는 없습니다.
void main()
{
Knight k;
int& hp = k.GetHp(); //< 일단 문제는 없음
}
void SetHp(T& data) 같은 경우는 별다른 문제 없지만,
데이터 복사 용도로만 쓸 것이라면 const T&가 더 바람직합니다
(물론 int 하나라면 참조를 넘길 필요는 없겠죠)
0