참조 Reference
값 전달의 단점
* 값 전달은 원본 전체를 복사한다.
크기가 큰 구조체나 클래스를 전부 복사할 때
스택이라면 크기가 부족할 가능성이 높으며,
힙이라도 (복사를 원하는 게 아니라면) 비효율적이다.
(이런 단점 때문에 포인터를 사용한다.)
* 위에 단점을 극복하거나 범위 밖에서도 값을 사용하고 싶다면 포인터를 사용해야 한다.
하지만 포인터는 실수가 쉽고, 큰 오류로 이어질 수 있다.
* 참조는 원본 전체를 복사하지 않으면서 포인터보다 안전하다.
즉, 참조는 포인터를 더욱 안전하고 사용하고 싶은 생각에서 나왔다.
* 참조는 const 포인터라고 생각하면 이해하기 쉽다.
예제
// 참조 선언
int main() {
int num = 10;
int& ref = num;
ref = 11;
cout << "참조 ref에 의해 num 값이 " << num << "로 바뀌었다." << endl;
return 0;
}
* int& ref 가 바로 참조자이다.
int& ref = num; 은 ref가 num의 별칭이라는 뜻이다.
* ref의 값을 바꾸는 것은 num의 값을 바꾸는 것과 동일하다.
보다 안정적인 참조
* 참조는 포인터보다 안정성을 높이기 위해 몇 가지 규칙이 있다.
* 참조는 선언할 때부터 유효한 값을 가지고 있어야 한다.
1. 선언과 동시에 초기화가 이루어져야 한다.
2. 참조는 NULL일 수 없다.
* 참조는 대상을 바꿀 수 없다.
초기화된 대상을 끝까지 참조한다.
* 즉, 선언된 순간부터 유효한 상태이며,
하나만을 참조한다.
함수 인자로 받는 참조
void swap(int& num1, int& num2) {
int tmp = num1;
num1 = num2;
num2 = tmp;
}
int main() {
int num1 = 10;
int num2 = 20;
swap(num1, num2);
cout << "num1 : " << num1 << endl;
cout << "num2 : " << num2 << endl;
return 0;
}
* swap(num1, num2); 에서 마치 값을 인자로 넘기는 것 같지만
실제로는 참조가 넘어가고 main에 있는
지역 변수인 num1, num2의 값에 변화가 적용된다.
힙에서도 사용 가능한 참조
class Vector {
public:
int x; int y; int z;
Vector(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {}
};
int main() {
Vector* vector = new Vector(1, 2, 3);
Vector& ref = *vector;
ref.x = 10; ref.y = 20; ref.z = 30;
cout << vector->x << ' ' << vector->y << ' ' << vector->z << endl;
return 0;
}
* new 연산자를 사용해 힙에 생성된 객체에도
참조를 사용할 수 있다.
메모리를 차지하지 않는 참조
* 포인터의 경우, 무조건 메모리를 차지하며 주소를 가지고 있다.
참조는 무조건 메모리를 차지하지는 않는다.
<예상>
* 참조는 무조건 하나의 원본을 가지고 바뀌지 않기 때문에
이는 컴파일 타임에서 참조 대상을 알 수 있다.
* 컴파일 타임에 원본이 누군지 알며, 원본이 바뀌지 않는다면
포인터처럼 주소를 가지고 있을 필요가 없다.
참조하는 곳에 원본을 바로 집어넣는 방법을 사용할 수 있다.
즉, 컴파일러는 상황에 따라 참조를 아예 원본으로 바꾼다.
상수 참조
* 기본적으로 상수를 참조할 수 없다.
* const 참조자는 사용할 수 있지만,
int num2 = ref1; 처럼 값 복사에만 사용할 수 있다.
참조 특징과 할 수 없는 것들
* 참조는 상수를 참조할 수 없다.
* 참조를 참조할 수 없다.
* 참조를 배열로 만들 수 없다.
참조는 메모리 상에 존재하지 않을 수 있기 때문에
배열처럼 연속된 메모리 형태를 할 수 없다.
귀여운 그림은 쭐어님이 그리셨습니다.
'C++' 카테고리의 다른 글
[C++] STL - Standard Template Library (0) | 2022.12.22 |
---|---|
[C++] 유니크 포인터 unique_ptr (0) | 2022.07.10 |
[C++] 가상 소멸자 (0) | 2022.07.02 |
[C++] 동적 바인딩, 정적 바인딩 (1) | 2022.06.30 |
[C++] friend 키워드 (2) | 2022.06.23 |