레퍼런스(Reference)
- C언어에서는 어떠한 변수를 가리키고 싶을 땐 반드시 포인터를 사용
- 하지만, C++에서는 다른 변수나 상수를 가리키는 방법으로 참조자라는 또다른 방식을 제공
#include <iostream>
int main()
{
int a = 3;
int& anotherA = a;
anotherA = 5;
std::cout << "a : " << a << std::endl;
std::cout << "anotherA : " << anotherA << std::endl;
return 0;
}
output
a : 5
anotherA : 5
- a의 참조자 antoherA를 정의함
- 가리키고자 하는 타입 뒤에 &를 붙이면 된다.
- anotherA는 a의 또다른 이름이라고 컴파일러에게 알려주는 것
- anotherA에 어떠한 작업을 수행하든 사실상 a에 그 작업을 하는 것
포인터와의 차이점
- 레퍼런스는 포인터와 상당히 유사하지만 레퍼런스는 몇가지 중요한 차이점이 있다.
레퍼런스는 반드시 처음에 누구의 별명이 될 것인지 지정
- 레퍼런스는 정의 시에 반드시 누구의 별명인지 명시해야 함
int& anotherA; // 불가능
- 위 문장은 불가능함. 하지만 포인터의 경우
int* p;
- 전혀 문제가 없음
레퍼런스가 한 번 별명이 되면 절대로 다른 이의 별명이 될 수 없다.
- 레퍼런스는 한 번 어떤 변수를 가리키게 되면 더 이상 다른 변수를 참조할 수 없다.
int a = 10;
int& anotherA = a;
int b = 3;
anotherA = b // a = b
- anotherA에 a를 참조하라고 한 이후 antoherA에 대입 연산을 하는 순간 a = b가 된다.
레퍼런스는 메모리 상에 존재하지 않을 수 있다.
- 하지만 포인터는 메모리가 존재
상수에 대한 참조자
#include <iostream>
int main()
{
int &ref = 4; // 컴파일 에러
std::cout << ref << std::endl;
}
- 레퍼런스로 상수를 가리키는 것은 C++ 문법에 올바르지 않다.
- 리터럴을 수정할 수 없기 때문
- 대신 아래와 같은 방법으로 참조할 수 있음
const int& ref = 4;
- 상수 참조자로 선언한다면 리터럴도 참조할 수 있다.
배열 레퍼런스
- 레퍼런스는 반드시 정의와 함께 초기화를 해줘야함
int a, b;
int& arr[2] = {a, b}; // 컴파일 오류
- 레퍼런스의 배열은 C++ 문법 상 불법이다.
- C++에서 배열의 이름은 첫 번째 원소의 주소값으로 변환이 될 수 있어야 함
- 이 때문에 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;
}
output
231
- ref가 arr을 참조하도록 하였음
- 따라서 ref[0]부터 ref[2]가 각각 arr[0]부터 arr[2]의 레퍼런스가 된다.
- 포인터와는 다르게 배열의 레퍼런스의 경우 참조하기 위해선 반드시 배열의 크기를 명시해야 함
레퍼런스를 리턴하는 함수
int& function(int& a)
{
a = 5;
return a;
}
int main()
{
int b = 2;
int c = function(b);
return 0;
}
- function은 인자로 받은 레퍼런스를 그대로 리턴하고 있다.
- function(b)를 실행한 시점에서 a는 main의 b를 참조하고 있게 된다.
- 따라서 function이 반환한 참조자는 아직 살아있는 변수인 b를 계속 참조 함
참조자가 아닌 값을 리턴하는 함수를 참조자로 받기
#include <iostream>
int function()
{
int a = 5;
return a;
}
int main()
{
const int& c = function();
std::cout << "c : " << c << std::endl;
return 0;
}
output
c : 5
- 함수의 리턴값은 스코프에서 나오게 된다면 소멸되는 것이 정상
- 따라서 int&로 받았을 때에는 컴파일 자체가 되지 않음
- 하지만 예외적으로 상수 레퍼런스로 반환 받게 된다면 해당 리턴 값의 수명이 연장된다.
- 연장되는 기간은 레퍼런스가 사라질 때 까지
출처
'C++' 카테고리의 다른 글
[C++] 가상 상속 (0) | 2024.12.17 |
---|---|
[C++] explicit와 mutable (0) | 2024.12.16 |
[C++] 이름 공간 (0) | 2024.12.16 |
[C++] Override와 final 키워드 (0) | 2024.12.13 |
[C++] 구조적 바인딩 (0) | 2024.12.13 |