inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part1: C++ 프로그래밍 입문

참조값 반환 질문

177

움직이는YM

작성한 질문수 86

0

Rookiss님 답변에서 궁금한 점이 생겼습니다.

은닉성 답변에서

void main()
{
   Knight k;
  int& hp = k.GetHp(); //< 일단 문제는 없음
}

이런 표현을 써주셨습니다.

제가 항상 헷갈리던게 반환형이 참조형이면 뭐가 반환되는가가 헷갈렸습니다.

예를 들어,

class Knight

{

public:

 

int _hp;

int& GetHp()

{

return _hp;

}

};

int main()

{

Knight k;

k._hp = 100;

int a = k.GetHp();

int& b = k.GetHp();

return0;

}

이런식으로 되어 있을 때

a와 b에서 일어나는 일의 차이를 잘 모르겠습니다

위 코드를 디스어셈블리로 살펴보면

int a = k.GetHp();

00A71939  lea         ecx,[k]  

00A7193C  call        Knight::GetHp (0A710B9h)  

00A71941  mov         eax,dword ptr [eax]  

00A71943  mov         dword ptr [a],eax  

int& b = k.GetHp();

00A71946  lea         ecx,[k]  

00A71949  call        Knight::GetHp (0A710B9h)  

00A7194E  mov         dword ptr [b],eax 

 ==> 이 실행문이 a에 하나 더 있는 걸 제외하고는 차이가 없습니다.

00A71941  mov         eax,dword ptr [eax]  

1. 참조값을 반환 한다는게 뭘 반환해 준다는 건가요?

- 예전 참조기초 강의에서

int* pointer = &number;

00BA2A59  lea         eax,[number]

00BA2A5C  mov         dword ptr [pointer],eax

*pointer = 2;

00BA2A5F  mov         eax,dword ptr [pointer]

00BA2A62  mov         dword ptr [eax],2

int& reference = number;

00BA2A68  lea         eax,[number]

00BA2A6B  mov         dword ptr [reference],eax

이 어셈블리를 통해 int*로 선언된 변수나 int&로 선언된 변수 모두 number의 주소를 담는 바구니라는 것을 확인했습니다.

위와 같은 사실로 제가 생각해 봤을 때,

-> 제 생각 :

반환형이 int& 라면-> 참조값 &, 포인터처럼 주소를 담는 바구니는 돌려준다

                        -> 그 바구니를 따라가다보면 나오는 데이터는 int형이다.

int a = k.GetHp()의 뜻 -> 바구니를 따라가다보면 나오는 int형 데이터를 복사해서 a라는 바구니에 대입해주겠다.

int& b = k.GetHp()의 뜻 -> 

00A7194E  mov         dword ptr [b],eax 
여기서 eax가 return시 [_hp의 주소]를 가지고 있다는 것을 확인했습니다.

(008550C9  call        Knight::GetHp (08510B9h)  를 F11로 들어가 확인해봤습니다)

즉 b는 _hp의 주소를 가지는 변수이다 -> 그런데 왜 메모리에서 &b를 찍으면 b의 주소에 _hp의 주소가 뜨는게 아니고 100이라는 값이 정확히 뜰까? -> C++에서는 참조라는게 그렇게 작동하니까

결국 리턴 값이 참조형으로 되어있으면 리턴되는 변수의 주소값이 넘어오는 것이다.

위와 같은 결론이 맞는 생각인지 궁금합니다.

C++

답변 2

1

Rookiss

int a = k.GetHp()의 뜻 -> 바구니를 따라가다보면 나오는 int형 데이터를 복사해서 a라는 바구니에 대입해주겠다.

그게 맞습니다. 사실 눈으로 코드를 이해하려 하지 마시고
항상 메모리를 까보면 더 확실히 알 수 있습니다.


00A71941  mov         eax,dword ptr [eax]  
이 코드의 의미는 [eax 레지스터에 저장된 주소로 이동해서, 그 값을 다시 eax 레지스터에 저장]하는 것인데
원래 eax에는 _hp의 주소가 있고, 거길 이동해서 값을 꺼내서 eax에 저장하는 것입니다.
여기서 참조값은 해당 변수의 주소값을 이야기 하는것입니다.
이건 포인터나 참조나 별다른 차이가 없습니다.

두번째로 왜 &b를 하면 _hp의 주소가 뜨는게 아닐까?
~라는 질문을 하셨는데 매우 일리 있는 질문입니다.
C++ 관점에서 보면 참조란 결국 [원본을 건드리는] 형태로 동작하는 것입니다.
그리고 구체적으로 그것을 어셈블리로 변환했을 때 어떻게 만들지는 컴파일러 자유이고
C++ 관점을 훼손하지 않는 선에서 자유롭게,
최대한 빠르게 동작하는 코드를 만들 수 있습니다.
위의 경우에는 b라는 변수를 위한 공간을 따로 할당해서 주소를 넣기 보다는,
그냥 k._hp를 그대로 사용하는 쪽을 선택했고
그리하여 b는 사실상 C++에선 존재하지만,
어셈블리로 변환이 되면 '존재하지 않는' (k._hp랑 동일한) 아이로 인식되어
&b을 해도 우리가 예상한 주소 값이 들어있지 않은 것입니다.
참고로 이렇게 바로 사용하는 것으로 최적화가 가능한 이유는 
참조 특성상 값이 한 번 정해지면 더 이상 수정이 불가능하기 때문입니다.

0

움직이는YM

자세한 답변 감사합니다!

visualstudio에서 파일분할관리실습시 설정 문의를 드립니다.

0

541

1

정렬함수 좀 더 확실하게 이해 할 방법이 있을까요?

0

442

1

strcpy() 구현 관련 질문

0

513

1

빌드(망치)를 누르니 이런 오류가 떴습니다. 어떻게 해야 하나요?

0

453

1

클래스 타입의 포인터 질문합니다

0

546

1

입력값을 enum 값에 넣어주는거 이제 막혔나요?

0

498

1

템플릿 특수화 관련 질문

0

385

1

포인터 관련 질문합니다!

0

265

1

Unable to start assembler. Check your settings.

0

831

2

cpu선택

0

539

1

포인터 질문이 있습니다

0

324

1

20:35 에서 구조체 크기에 대한 질문입니다!

0

585

1

iterator 삭제관련

0

406

1

함수 호출을 디스어셈블러로 분석하다가 궁금점이 생겼습니다!

0

310

1

15 분 45초 대 질문

0

309

0

스택 프레임 질문합니다!

2

306

1

오른값 참조 in 게임

0

384

0

동적할당 질문이 있습니다

0

450

1

안녕하세요 메모리에 대해 질문드립니다.

0

305

1

함수객체 의 매개변수

0

360

1

복사생성자

0

434

1

main이나 endl 부분이 주황색으로 표시된건 어떻게 하나요

0

421

1

포인터 실습 강의를 보고 궁금한게 있습니다.

0

355

1

스택 오버플로우

2

790

1