&
를 붙이면 된다.int
형 변수의 레퍼런스를 만들고 싶을 때에는 int&
를, double
의 레퍼런스를 만드려면 double&
로 하면 된다. int*
와 같은 포인터 타입의 레퍼런스를 만드려면 int*&
로 쓰면 된다.레퍼런스**는 한 번 별명이 되면 절대로 다른 이의 별명이 될 수 없다.
즉, 어떤 변수의 레퍼런스가 되버리면, 더 이상 다른 변수를 참조할 수 없게 된다.
int a = 10;
int* p = &a;
위 포인터 변수 p는 메모리 상에서 8 바이트를 차지한다.(32비트의 경우 4바이트)
int a = 10;
int& another_a = a;
레퍼런스의 경우 메모리 상에 존재하지 않게 된다. 물론 그렇다고 해서 항상 존재하지 않는 것은 아니고 아래 예와 같은 예외가 존재한다.
#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;
}
위에서 중요한 부분은 int change_val(int &p)
함수 선언부다. 레퍼런스의 경우 반드시 처음에 누구의 별명이 될 것인지 정해줘야 한다는 규칙이 있어 이 같은 선언은 문제가 있을 것으로 보이지만 사실 p가 정의되는 순간은 change_val(number)
로 호출할 때 이므로 사실상 int& p = number
가 실행된다고 보면 된다. 그렇기 때문에 전혀 문제가 없는 선언이다.
#include <iostream>
int main() {
int& ref = 4; // 에러가 발생하는 구문
std::cout << ref << std::endl;
}
위 코드는 에러가 발생하는데 그 이유는 상수값 자체는 리터럴이기 때문이다.
리터럴은 그 차체로 변경할 수 없는 값인데 위 같은 코드가 실행된담녀 ref = 5;
와 같이 리터럴의 값을 바꾸는 행위가 가능하게 된다.
따라서 C++ 문법상 상수 리터럴을 일반적인 레퍼런스가 참조하는 것은 불가능하게 돼있다.
const int& ref = 4;
단 예외적으로 상수 레퍼런스로 선언하면 리터럴도 참조 할 수 있다.
int a, b;
int& arr[2] = {a, b};
위 코드와 같은 레퍼런스 배열의 정의는 에러를 발생 시킨다.
C++의 문법 상 배열의 이름은 (arr)의 첫 번째 원소의 주소값으로 변환이 될 수 있어야 한다. 이 때문에 arr[1]
과 같은 문장이 *(arr + 1)
로 바뀌어서 처리될 수 있다.
그런데 주소값이 존재한다는 의미는 해당 원소가 메모리상에 존재한다라는 의미와 같다.
하지만 레퍼런스는 특별한 경우가 아닌 이상 메모리 상에서 공간을 차지 하지 않는다. 따라서 이러한 모순 때문에 레퍼런스들의 배열을 정의하는 것은 언어 차원에서 금지되어 있다.
그렇다고 해서 그와 반대인 배열들의 레퍼런스가 불가능한 것은 아니다.
#include <iostream>
int main() {
int arr[3] = {1, 2, 3}
int (&ref)[3] = arr;
ref[0] = 2;
ref[1] = 3;
ref[2] = 1;
std::cout << arr[0] << arr[1] << arr[2] << std::endl;
return 0;
}
ref
가 arr
배열을 참조하도록 했다.
따라서 ref[0]
부터 ref[2]
가 각각 arr[0]
부터 arr[2]
의 레퍼런스가 된다.
포인터와는 다르게 배열의 레퍼런스의 경우 참조하기 위해선 반드시 배열의 크기를 명시해야 한다.
따라서 int (&ref)[3]
이라면 반드시 크기가 3인 int
배열의 별명이 되어야 하고 int (&ref)[5]
라면 크기가 5인 int
배열의 별명이 되어야 한다.
int function() {
int a = 2;
return a;
}
int main() {
int b = function();
return 0;
}
문제 없이 컴파일이 완료되면 b에 a의 값이 복사되어 저장된다. 즉, 값만 복사되고 a는 메모리에서 해제된다.
int& fucntion() {
int a = 2;
return a;
}
int main() {
int b = function();
return 0;
}
이 코드는 런타임 에러를 발생시킨다.
function
의 타입은 int&
이며 참조자를 리턴하게 된다.
그런데 문제는 function
안에 정의되어 있는 a
는 함수의 리턴과 함께 사라진다는 것이다.
레퍼런스를 리턴하면서 원래 참조하고 있던 변수가 이미 사라져버렸으므로 오류가 발생하게 된다.
이와 같이 레퍼런스는 있는데 원래 참조 하던 것이 사라진 레퍼런스를 댕글링 레퍼런스(Dangling reference)라고 부른다.
💡 **따라서 레퍼런스를 리턴하는 함수에서 지역 변수의 레퍼런스를 리턴하지 않도록 조심해야 된다.**외부 변수의 레퍼런스를 리턴
int& function(int& a) {
a = 5;
return a;
}
int main() {
int b = 2;
int c = function(b);
return 0;
}
function(b)
를 실해한 시점에서 a
는 main
의 b
를 참조하고 있게 된다.function
이 리턴한 참조자느 아직 살아있는 변수인 b
를 계속 참조 한다.레퍼런스를 리턴하는 경우의 장점