[C++] 래퍼런스 (vs. 포인터)

2024. 4. 1. 11:27Programming Language/C++

포인터 및 래퍼런스 문법 요약

• 자료형* 변수명; ➜ 포인터 변수 선언 (자료형* 타입의 변수)

• *포인터변수; ➜ 포인터로 주소 역참조 (포인터 변수에 저장되어 있는 주소로 역참조 한다.)

• &변수; ➜ 변수의 주소값 (본인의 주소값을 반환)

• 자료형& 변수명; ➜ 래퍼런스 변수 선언

원본에 접근할 수 있는 방법인 포인터 말고도 C++에서 래퍼런스가 추가됐다.


래퍼런스(Reference) `&`

• C++에 추가된 기능으로, 포인터와 유사하다.

참조한 원본을 전달한다.

• 참조 변수를 통해서 직접적으로 원본을 수정할 수 있다.

래퍼런스를 사용하는 이유

크기가 큰 원본을 그대로 전달하면 복사 비용이 많이 든다.

포인터 변수는 주소를 통해서 접근하기 때문에 원본의 크기는 고정적이다.

그래서 비용을 줄이기 위해 래퍼런스로 원본을 참조하면 원본 전체를 복사하는 비용을 줄일 수 있다.

래퍼런스 장점

• 한 번 참조받으면 다른 변수로 바꿀 수 없기 때문에 주소 연산 실수의 여지가 줄어든다.

주소로 접근해서 변경시킬 수 있는 위험 요소가 없다. (ex. 잘못된 주소로 오버해서 접근하는 등의 문제)

• 값을 변경할 때 역참조 연산을 할 필요가 없고, 즉시 수정이 가능하다.

포인터는 매번 역참조 연산을 명시해 줘야 원본으로 접근할 수 있는 반면, 래퍼런스는 본인이 참조받자마자 그 변수를 즉시 수정할 수 있는 형태이므로 내가 원하는 형태의 함수를 설계하는 데 있어서 중요하다.

호출 방식 자체의 변화가 래퍼런스의 중요한 의미 중 하나이다.

▷ 예시

int& iRef = a;  // iRef는 a만 참조한다. 즉, iRef는 곧 a이다.
iRef = 100;  // iRef를 수정

포인터와 래퍼런스

• 다른 변수나 주소를 통해 값을 간접적으로 접근할 수 있다.

• 어떤 변수에 연결되어 그 변수를 수정하거나 읽을 수 있다.

• 함수 인자로 사용되어 원본 데이터를 수정할 수 있다.

포인터 vs. 래퍼런스

  포인터 래퍼런스
초기화 선언 후 나중에 초기화 가능  선언 시 반드시 초기화 필요
null 가능 여부 nullptr 또는 null로 초기화할 수 있다. null값을 가질 수 없고,
항상 유효한 변수에 연결되어야 한다.
변경 가능 다른 변수의 주소를 가리킬 수 있다. 한 번 가리키면 다른 변수로 변경할 수 없다.
사용 방법 * 연산자로 값을 참조하거나,
-> 연산자로 멤버에 접근한다.
변수처럼 사용 가능하고, 추가적인 연산자는 필요하지 않다.
메모리 크기 주소를 저장하므로 크기가 고정적이다.
(4byte 또는 8byte)
참조 대상에 따라 내부 동작이 달라지며, 그 크기는 알 수 없다.

▷ 포인터

// 주소를 받고 역참조해서 값을 수정한다.
int a = 10;
int* ptr;
ptr = &a;  // 초기화 나중에 가능
*ptr = 100;

 

▷ 래퍼런스

// iRef가 a를 참조해서 수정하는데, iRef를 수정하는게 곧 a를 수정하는 것이다.
int& iRef = a;  // 초기화 필요
iRef = 100;

const 포인터와 const 래퍼런스

• 값을 변경할 수 없다.

• 읽기 전용 데이터를 함수에 전달할 때 유용하다.

const 래퍼런스 vs. const 포인터

1) const 포인터

• 가리키는 값은 변경할 수 없지만, 다른 변수로 변경할 수는 있다.

 

2) const 래퍼런스

• 처음에 한 번만 참조하고 다른 변수나 값으로 변경이 불가능하다.

• const 래퍼런스는 const 포인터 const와 유사하다.

 

▷ const 포인터 vs. const 래퍼런스

// const 포인터처럼 래퍼런스로 참조를 받았지만 원본을 수정하고 싶지 않을때
// 1. const 포인터
const int* p2 = &a;
//*p2 = 10;  // 값 변경 불가능

// 2. const 래퍼런스
const int& iRefConst = a;  // const int* const p2 = &a;
//iRefConst = 10;  // 값 변경 불가능