참조자도 메모리 공간에 할당되나요?

흔히 C++의 참조자를 설명할 때 참조 대상에 붙이는 새로운 이름이라고 설명하는데 인터넷에 보니까 익명으로 가려진 변수가 할당된다는 말도 있어서 조금 헷갈리네요. 참조자 선언 시 새로운 변수가 메모리 공간에 할당되나요?

1답변

  • 좋아요

    1

    싫어요
    채택취소하기

    http://en.cppreference.com/w/cpp/language/reference 에서 아래와 같은 내용을 볼 수 있습니다.

    References are not objects; they do not necessarily occupy storage, although the compiler may allocate storage if it is necessary to implement the desired semantics (e.g. a non-static data member of reference type usually increases the size of the class by the amount necessary to store a memory address).

    참조자는 객체가 아니기 때문에 저장 저장 공간을 반드시 필요하지 않지만, 컴파일러가 필요하다면 구현에 따라 저장 공간을 차지할 수 있다는 내용입니다. 즉, 메모리 공간에 할당될 수 도 있고 안될 수 도 있습니다.

    위에서도 말했듯이 참조자는 객체가 아니기 때문에 sizeof 를 통해 크기를 측정할 수 없습니다. sizeof(int&)sizeof(int) 의 값과 동일하게 계산됩니다. 따라서 아래와 같은 방법을 통해 참조자의 크기를 측정할 수 있습니다.

    #include <iostream>
    
    struct IntRef {
        int& ref;
    };
    struct CharRef {
        char& ref;
    };
    int main() {
        std::cout << "sizeof int& : " << sizeof(IntRef) << std::endl;
        std::cout << "sizeof char& : " << sizeof(CharRef) << std::endl;
        std::cout << "sizeof void* : " << sizeof(void*) << std::endl;
        return 0;
    }
    

    위 코드를 실행한 결과는 아래와 같습니다. 크기는 시스템 마다 다를 수 있으나 void* 와 참조자의 크기가 같은 것을 볼 수 있습니다.

    sizeof int& : 8
    sizeof char& : 8
    sizeof void* : 8
    

    어셈블리를 확인하여 크기를 알 수 도 있는데요. 아래는 참조자를 사용한 C++ 코드를 GCC 7.3 으로 컴파일 했을 때의 어셈블리 코드 입니다(https://godbolt.org/g/peksus).

    int main() {
        int value = 10;
        int& ref = value;
        int* ptr = &value;
        return 0;
    }
    
    main:
      push rbp
      mov rbp, rsp
      mov DWORD PTR [rbp-20], 10
      lea rax, [rbp-20]
      mov QWORD PTR [rbp-8], rax
      lea rax, [rbp-20]
      mov QWORD PTR [rbp-16], rax
      mov eax, 0
      pop rbp
      ret
    

    여기서 mov QWORD PTR [rbp-8], raxint& ref = value;, mov QWORD PTR [rbp-16], raxint* ptr = &value; 의 내용입니다.

    rbp 다음의 숫자만 다른것을 볼 수 있습니다. 즉, 참조자는 포인터와 실제 동작이 동일하며 rbp-20 가 아닌 rbp-8 이란 위치에 자신만의 메모리 공간을 차지합니다.

    정리하면 표준상 참조자는 메모리 공간을 반드시 필요하지 않으나 컴파일러의 구현에 따라 메모리 공간을 차지하며, 그 크기 역시 구현에 따라 다르지만 일반적으로 포인터와 같은 크기의 메모리 공간을 차지합니다.

    • 답변 감사합니다! 인터넷을 보니까 참조자 선언 시 컴파일러가 내부에서 const 포인터를 새로 할당해서 그걸로 계산을 한다는 말도 있더라구요. 근데 외부에서 접근은 불가능하니 참조자 자체가 메모리에 할당되는 건 아니라고 봐야겠네요. 어쨌든 자세한 답변 감사드립니다. JKrig 2018.2.9 13:27
    • const 포인터를 생성하는 것처럼 동작합니다. 하지만 C++ 에서 그 포인터 변수에 직접 접근하는 것은 불가능합니다. 공기는 보이지 않고 만져지지 않지만 존재하는 것 처럼, 참조자도 실제론 메모리가 할당되어 존재합니다. 유동욱 2018.2.9 13:40

ᕕ( ᐛ )ᕗ
로그인이 필요합니다

작성한 답변에 다른 개발자들이 댓글을 작성하거나 댓글에 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.