참조자와 포인터 차이(C++)

Jo·2021년 8월 14일
1

c++공부를 시작하게 되면서, 기존에 공부했던 c언어에는 없었던 새로운 개념을 알게 되었다. 바로 참조자(레퍼런스)인데, 이번 포스팅에서는 참조자의 정의와 c언어에 있는 포인터와의 차이점을 다루려 한다.

c언어에서 포인터를 사용하여 변수를 가리키는 것과 같이, c++에서 변수/상수를 가리키는 또다른 방식으로 참조자(레퍼런스)를 제공한다.
이에 대한 기본적인 사용방법은 다음과 같다.

#include <iostream>
using namespace std;
int main() {

int a=3;
int& a_plus=a;
a_plus = 5;
cout << "a: " << a << endl;
cout << "a_plus: " << a_plus << endl;
return 0;

}

이를 컴파일하면 다음과 같은 결과가 나온다.

a_plus라는 참조자를 정의하여 변수 a를 가리키고, a_plus에 5로 할당한 모습이다. 출력결과를 보면 알다시피, a의 값 또한 5로 변경되었다. 이는 c언어에서 사용하는 포인터와 굉장히 유사한 방식이다. 그러나 *나 &를 사용하지 않는다는 점에 있어 훨씬 코드가 간결해진다는 장점이 있다.

다만 참조자에는 몇가지 제약사항이 있는데,

  1. 참조자만 단독으로 정의하지 못한다. 포인터는 단독정의가 가능하지만, 참조자를 단독정의할 경우 에러가 발생한다. 그 이유는 메모리를 할당하는 방식이 다르기 때문이다. 포인터는 정의와 동시에 그에 맞는 메모리가 할당되지만, 참조자는 메모리를 차지하지 않는다. 참조자는 변수의 값을 그대로 대체한다고 볼 수 있다.

  2. 포인터와 딜리 참조자는 일단 정의하면 가리키는 변수를 바꿀 수 없다. 포인터는 변수 a를 가리켰다가도 같은 포인터 변수로 b를 가리킬 수 있지만, 참조자는 에러가 발생하낟.

  3. 참조자(레퍼런스)는 참조자의 참조자, 참조자의 배열, 참조자의 포인터는 존재할 수 없다. 이는 c++의 공식 규정에 나와있는 사실이다.

*다만, 배열들의 레퍼런스는 가능하다.

#include <iostream>
using namespace std;
int main() {
	int arr[3] = { 1,2,3 };
	int(&arr_plus)[3] = arr;

	arr_plus[0] = -1;
	arr_plus[1] = -2;
	arr_plus[2] = -3;

	cout << arr[0] << arr[1] << arr[2] << endl;


	return 0;
}


이러한 방식으로 거꾸로 배열들에 참조자를 정의하면 arr_plus[0]에는 arr[0]이, arr_plus[1]에는 arr[1]이 ... 이런 방식으로 대체된다. 그러나 이는 레퍼런스의 배열과는 다르다는 점을 알아두자. 만약

int a, b;
int& arr[2] = {a, b};

이러한 방식으로 하면 오류가 발생한다.

  1. 마지막으로 함수에서 일반 값을 리턴하는 것과, 레퍼런스 값을 리턴하는 점에서 차이가 있다. 이는 표로 간단히 알아보도록 하자.

(이미지 출처: https://modoocode.com/141)

profile
이것저것 배우고 싶은 대학생

1개의 댓글

comment-user-thumbnail
2022년 8월 10일

감사합니다.

답글 달기