본문 바로가기
CODING/C++ STUDY

C++ 독학 3일차 레퍼런스 도입

by pharmerci 2021. 7. 20.
728x90

이제부터 C++을 시작하는 기분이 든다. 새로운 개념인 참조자에 대해서 공부해볼 거니까!

참조자 하면 &가 생각나곤 하는데, 내가 생각하는게 아니겠지? 무시하고 넘어가봅시다.

 

위와 같이 코드를 입력하면 차례대로 5와 3이 출력된다.

이전에 했던 것들이기도 하고 c언어에서도 볼 수 있었던 코드라 어렵지 않다.

change_val함수의 인자 p에다가 number의 주소값을 전달해서 *p를 통해 number을 참조하여 number값을 바꿨다.

 

c언어에서 어떤 변수를 가리키고 싶다면 포인터를 이용했다.

c++에서는 다른 변수나 상수를 가리키는 방법으로 이 방법 말고도 다른 방식을 제공한다.

 

그것이 바로 참조자, 레퍼런스이다.

 

 

 

 

이것이 바로 레퍼런스를 이용한 코드이다. 한줄씩 분석하며 공부해보자.

5 | int a=3;

int형 변수 a를 정의하고 3이라는 값을 넣었다.

 

6 | int & another_a=a;

여기가 하이라이트이지 싶다..! another_a는 a의 참조자이다. 이 말은 another_a는 a의 또다른 이름이라고 컴파일러에게 알려주는 것과 같다.

 

another_a에게 작업을 수행하는 것은 a에 작업을 하는 것이나 마찬가지이다.

 

8번째 줄에서 another_a를 5로 정하고 a와 another_a를 차례대로 출력했더니 둘다 5로 출력되었다.

a는 원래 3이었고 아무런 변형을 주지 않았지만 a의 참조자인 another_a 값을 설정해주었기 때문에 같이 바뀐거다.

 

참조자는 포인터랑 비슷한것 같다. 변수의 주소값을 보관해서 간접적으로 연산을 하니까.

 

 

근데 참조자와 포인터는 차이점이 존재한다.

 

1. 레퍼런스는 처음에 누구의 별명이 될 것인지를 지정해야 한다.

 

int *p;는 가능하다. 하지만 int &p;는 불가능하다는 뜻이다.

그래서 레퍼런스를 사용할 때는(지금 보니까 레퍼런스와 참조자의 혼용이 심각하군요.. 그냥 그런가보다 해줘요) int &p=a; 이런식으로 적시를 해줘야한다.

 

2. 레퍼런스가 누군가의 별명이 되면 다른 사람의 별명이 될수는 없다.

 

간단한 코드니까 여기다가 써볼게요

 

int a=10;

int &another_a=a;

 

int b=3;

another_a=b;

 

이런 코드가 있다고 가정해보자구요 일단 위에 두번째 코드는 아까 한거니까 어렵지 않죠?

처음에 레퍼런스를 설정해준거구, 그 밑에 두줄은 무슨 의미인가.

일단 b 변수를 설정했고 3으로 정했어요

맨 마지막 줄은 another_a가 b의 참조자이다. 이게 아니라!!

그냥 another_a라는 변수에다가 b값을 대입한겁니다. 그니까 another_a를 출력하면 3이 출력되겠죠?

 

그렇다면 a를 출력하면 무슨 수가 나올까요? 당연히 3입니다.

 

그럼 포인터 코드도 살짝 볼까요? 전 어려우니까요..

 

int a=10;

int *p=&a;

 

int b=3;

p=&b;

 

이 코드의 경우에는 a의 포인터였던 p가 b의 포인터로 갈아타는 모습을 볼 수 있어요

그러니까 저 코드가 쓰여진 상태에서 a와 p가 가리키는 주소 안에 있는 값과 b의 값을 각각 출력한다면

 

a=10, b=3, p가 가리키는 주소 안에 있는 값=3

 

이렇게 되겠죠?

 

3. 레퍼런스는 메모리 상에 존재하지 않을 수도 있다.

 

먼저 포인터를 보죠!

int a=10;

int* p= &a;

이렇게 하면 p는 a의 주소값이니까 메모리 상에서 8바이트를 차지하게 돼요

 

그럼 레퍼런스는요?

int a=10;

int& another_a=a;

another_a랑 a는 어차피 똑같은거 아닌가요?? 그러니까 이럴 땐 레퍼런스가 메모리 상에 존재하지 않아요

 

 

 

 

포인터와 레퍼런스의 차이점을 알아봤으니 추가적으로 공부해볼 것들이 있다.

 

먼저 참조자의 참조자. 이런것은 존재하지 않는다.

int&&z=x; 이런 것은 없다는 것이다.

참조자의 참조자는 별명의 별명이라는 것이랑 똑같은데 우리도 친구들 별명의 별명까지는 안지으니까!?

그렇다고 생각합시다.

 

참조자의 장점이라고 한다면, &와 *를 불필요하게 쓸 필요가 없어진다는 것이다.

 

대표적인 좋은 예시는 변수 입력받는 함수인데,

 

c언어에서 보통 변수를 입력받을 때는

scanf("%d" , &a);

이런 식으로 &을 사용해서 변수의 주소값을 전달해줬었다.

 

근데 참조자를 이용하게 되면? c++에서는

std::cin>>a;

이것도 충분히 가능하다.

 

지금 방금 이야기한 장점을 얘기하지 않았으면 아마 계속 왜 이딴걸 써야하지? 라고 의문을 가졌을 것 같다..

 

 

 

레퍼런스의 배열과 배열의 레퍼런스!?

레퍼런스의 배열이라.. 이게 가능할까요?? 한번 도전해봅시다.

보시다시피 쓰지 말라네요 참조배열을 사용할수 없 습 니 다 .

array[0]=a 하고.. array[1]=b해주면 안되나?

array라고 배열을 정해주면 첫번째 원소의 주소값으로 변환이 되어야한다.

그래야 array[1] 이런게 *(array+1) 이런식으로 처리가 되기 때문이다.

 

주소값이 존재한다는 것은 원소가 메모리 상에 존재한다는 것이죠?

아까 레퍼런스의 특징이 메모리 공간을 안가지는 경우가 많다고했죠?

그러면 말이 안되죠?

그래서 레퍼런스의 배열이 금지가 된 것이라고 합니다.

 

 

다음은 배열의 레퍼런스예요.

 

arr이라는 배열에 1, 2, 3을 순서대로 넣어주고 ref가 arr을 참조하게 했습니다. 

말그대로 배열의 레퍼런스입니다.

그리고 ref에다가 2, 3, 1을 넣어주고 arr을 순서대로 출력하게 하니

1, 2, 3이 아닌 ref 변수에서 바꿔준대로 2, 3, 1이 출력되는 모습입니다.

배열의 레퍼런스가 실현되고 있는것이죠!? 근데 참조할 때 배열의 크기는 명시해줘야 한답니다.!

 

 

 

 

 

728x90