develop/C++

[씹어먹는 C++ - 2] 참조자

devdw 2021. 9. 1. 15:25

C언어에서 변수를 가리키고 싶을 때 사용하는 것 : 포인터

#include <iostream>

int change_val(int *p){
    *p = 3;

    return 0;
}

int main() {
    int number = 5;
    std::cout << number << std::endl;
    change_val(&number);
    std::cout << number << std::endl;
}

C++에서 변수나 상수를 가리키는 방법 : 참조자(reference)

가리키고자 하는 타입 뒤에 & 붙이기

  • 변수의 또다른 이름 (별명)
  • 정의 시 반드시 초기화 해야함
  • 한 번 정해지면 다른 변수로 참조자를 바꿀 수 없음
  • 일반적으로 메모리 상에 존재하지 않음
#include <iostream>

int main() {
    int a = 3;
    int& another_a = a; // another_a는 a의 참조자

    another_a = 5;
    std::cout << "a: "<< a << std::endl;
    std::cout << "another_a: "<<another_a << std::endl;

    return 0;
}
  • 상수 리터럴을 일반적인 레퍼런스가 참조하는 것은 불가능
// 불가능
int &ref = 4; 

// 가능 - a = 4
const int &ref2 = 4;
int a = ref2; 

장점

  • 불필요한 &와 * 가 필요없어서 코드가 훨씬 간결해짐

레퍼런스의 배열

int a, b;
int& arr[2] = {a, b}; // 불가능
  • C++에서 배열의 이름은 첫번째 원소의 주소값으로 변환될 수 있다.
    → arr[1] 과 * (arr + 1) 은 동일하게 처리됨
  • 주소값이 존재한다 == 메모리 상에 존재한다 는 뜻
  • 참조자는 일반적으로 메모리 상에서 공간을 차지하지 않기 때문에 참조자 배열은 불가능함

배열의 레퍼런스

int arr[3] = {1, 2, 3};
int(&ref)[3] = arr; //ref 가 arr을 참조
  • 참조할 때 반드시 배열의 크기를 명시해야 함

함수와 레퍼런스

변수 a의 값은 b에 복사되고 a는 함수 종료 시 a는 메모리 상에서 사라짐

int function(){
    int a = 1;
    return a;
}
int main() {
    int b = function();
    return 0;
}

레퍼런스 리턴 함수

함수는 a의 참조자를 반환한다. 그런데 변수 a는 함수 종료 시 사라진다.
참조자를 반환하면서 원래 참조하고 있던 a가 사라졌기 때문에 별명만 남겨져 오류를 발생시킨다.
원래 참조하던 것이 사라진 레퍼런스 → 댕글링 레퍼런스

int& function(){
    int a = 2;
    return a;
}
int main() {
    int b = function();
    b = 3;
    return 0;
}