Deeper Learning

References의 주소 본문

Game Development/C&C++

References의 주소

Dlaiml 2024. 4. 17. 11:23

간단한 C 공부를 마치고 C++ 문법에 대해 학습중이다. 모든 문법에 대해 포스팅을 하기 보다는 바로 받아들이지 못한, 의문이 생긴 개념에 대해 찾아보고 해결해가는 과정을 포스팅을 남기려한다

 

 

 

Question

Reference의 메모리 주소를 디버깅해보니 Initialize한 변수의 주소값과 동일함.

 

References

아래 예시코드 부터 보자

 

#include <iostream>

void byPointer(int* ptr) {
    *ptr = 20;
}

void byReference(int& ref) {
    ref = 30;
}

int main() {
    int num = 10; // 0x0000009EE52FF7D4 / 1E 00 00 00

    int* ptr = &num;

    byPointer(ptr);
    std::cout << "Address of ptr: " << &ptr << std::endl;
    std::cout << "Address of *ptr: " << &*ptr << std::endl;
    std::cout << "Address of num: " << &num << std::endl;
    std::cout << "Value after modification by pointer: " << num << std::endl;

    int& ref = num;
    
    byReference(ref);

    std::cout << "Address of ref: " << &ref << std::endl;
    std::cout << "Address of num: " << &num << std::endl;
    std::cout << "Value after modification by pointer: " << num << std::endl;

    std::cout << "Value after modification by reference: " << num << std::endl;

    return 0;
}


// Address of ptr: 0000005D89AFF708
// Address of *ptr: 0000005D89AFF6E4
// Address of num: 0000005D89AFF6E4
// Value after modification by pointer: 20
// Address of ref: 0000005D89AFF6E4
// Address of num: 0000005D89AFF6E4
// Value after modification by pointer: 30

 

Reference는 object의 alias라고 정의할 수 있다. ("The reference isn’t a separate object. It has no identity.")

즉 위 코드에서 ref는 num에 대한 pointer도 아니고, num의 copy 또한 아니다. 

num의 또다른 이름이다. (두 포인터가 하나의 메모리 주소를 가리키는 Shallow copy와 전혀 다름)

 

num에 처리를 하면 ref도 똑같이 영향을 받고 그 역도 동일하다.

 

이제 위 코드의 결과값을 보자

포인터 변수 ptr은 메모리 주소를 가지고 있으며 num의 주소가 해당 위치에 저장되어 있다. (Windows x64, Intel CPU 환경으로 Little Endian 사용)

 

물론 *ptr과 num의 주소는 동일하다

 

 

Reference의 경우를 보자

 

int num = 10; 이후의 메모리 현황이다.

ref 선언, 초기화 전

 

int& ref = num; 이후 메모리 현황이다 

ref 초기화 후

포인터 처럼 아래 0x000000D4BD6FF546 주소에 num의 주소인 0x000000D4BD6FF504가 저장되었다.

(연달아 선언한 자동 지역 변수라 비슷한 주소값을 가진 Stack 영역에 저장)

하지만 &ref는 num의 Alias이기 때문에 &num과 동일하다.

 

나의 추측은 Reference를 선언하고 초기화할 때 (Reference는 선언과 초기화를 동시에 해야함) Pointer를 사용하여 초기화하고 Reference의 주소를 초기화한 변수로 재할당하는 과정이 있을것이라고 생각한다. 

 

어차피 주소가 같은데 왜 필요한가? 라는 생각이 들면 아래 Swap 코드에서의 활용을 보면 Reference 사용 이유에 대해 더 생각해볼 수 있다. (Call by Value, Call by Reference, 함수 매개변수로 전달되었을 때 처리방법(Register, Memory)에 대해 더 찾아보는 것을 추천드립니다)

 

Pointer, References

#include <iostream>

void swapByReference(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

void swapByPointer(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 10, y = 20;

    std::cout << "Before swap by reference: x = " << x << ", y = " << y << std::endl;
    swapByReference(x, y);
    std::cout << "After swap by reference: x = " << x << ", y = " << y << std::endl;

    std::cout << "Before swap by pointer: x = " << x << ", y = " << y << std::endl;
    swapByPointer(&x, &y);
    std::cout << "After swap by pointer: x = " << x << ", y = " << y << std::endl;

    return 0;
}

 

각각 Pointer와 References로 구현한 Swap 함수다.

 

  • 함수 내부에서 매개변수의 값의 변경이 필요할 경우 Pointer나 References를 사용하는 것이 좋다.
  • 값의 변경이 필요하나 매개변수가 작을 경우 아래 코드에서 윗줄이 더 가독성이 좋은 코드이므로 Call by Value로 작성하여도 무방하다.
a = incr(a)

incr(a) // A increased in incr func

 

  • 매개변수가 큰 값이고 값으 변경이 함수내에 없다면 const Reference를 사용하는 것이 좋다.

 

 

 

Comments