알음알음-IT/개발_기초_코딩_C++

C++ 공부하기 - 6.참조자와 함수

구구닥스 2020. 2. 4. 14:28

저번 시간에 이어서 참조자에 대해서 공부하겠습니다.

참조자란 마치 별칭을 달아주는 것과 같이 쓰인다고 했습니다.

그러면 그 참조자를 함수에서는 어떻게 쓰는지 알아보겠습니다.

 

C언어에서 배운 함수 호출 종류로는 우선

Call-by-value가 있었고 다음으로 Call-by-reference(address)가 있었습니다.

포인터를 공부할 때 익히셨을꺼라 생각합니다.

간략하게 풀이해보면 Call-by-value는 값을 인자로 전달하는 함수 호출 방식이며 Call-by-reference는 주소 값을 인자로 전달하는 함수의 호출방식입니다.

 

차이점을 명확이 할려면 간단한 함수로 보는게 빠릅니다.

void Swap(int num1, int num2)                                          

{

int temp = num1;

num1 = num2;

num2 = temp;

}

이 함수는 Call-by-value로 값을 인자로 받는 함수입니다. num1,2,를 인자로 받아서 바꾸는 함수 같지만 실제로 실행해보면 값은 바뀌지 않습니다. 

지역변수안에서는 바뀌지만 외부에 선언된 변수에 개입을 할 수 없기 때문입니다.

그렇다면 포인터를 써서 주소 값을 인자로 받으면 어떻게 될까요?

void Swap2(int *num1, int *num2)

 

{

int temp = *num1;

*num1 = *num2;

*num2 = temp;

}

이렇게 포인터로 주소 값을 인자로 받으면 값이 바뀝니다.

 

보시는 것처럼 Swap2로 인자가 서로 바뀌었습니다.

차이점이 확실히 드러납니다. Call-by-value는 값을 인자로 Call-by-reference는 주소 값을 인자로 받는겁니다.

간혹 주소 값을 인자로 받아서 증감연산자로 증가시키거나 그런 경우가 있는데 이는 Call-by-value로 주소값을 참조하지 않았기 때문입니다.

이런 차이점을 알아두셔야 합니다.

 

위에 나온 Call-by-reference는 포인터를 이용했습니다만 이제부터는 참조자를 이용해서 Call-by-reference를 해보겠습니다.

함수의 매개변수를 참조자로 받아서 실행한 결과입니다. Call-by-reference로 주소 값을 인자로 받아 값을 바꾼거랑 똑같습니다.

다만 참조자를 사용하게 되다보면 함수의 호출문장만 가지고 함수의 특성이 파악할 수 없는 딜레마에 빠집니다.

거기다 매개변수에 참조자가 쓰여있다면 그 함수의 원형까지 다 확인해서 값의 변경이

일어나는가 안일어나는가 확인해야 하는 단점이 있습니다. 값을 바꿀 수 있는 대신 다 파악해야하는 단점입니다.

이러한 단점은 키워드 const를 사용하면 어느정도 방지할 수 있습니다. const를 사용하면 참조자를 이용한 값의 변경을 하지 않겠다

이정도로 해석이 됩니다.

 

이러한 단점으로 아예 참조자 대신 포인터만 쓰기도 한답니다.

 

또 반환형이 참조형인 경우가 있습니다.

매개변수 뿐만이 아니라 반환형에도 참조형을 사용할 수 있습니다, 꼭 사용해야하는 것이 아니라 사용 안할 수도 있습니다.

반환형을 참조자로하여 num2가 결국 num1을 참조하게 되어 num2-ref-num1식으로 참조하게 된것입니다.

보시면 num1에 처음 2의 값에다 Refer함수 안의 ++로 1이 증가하였고 그 아래로 +2 , +3을 하여 값은 8이 나옵니다.

num2도 num1을 참조하고 있기 때문에 값이 8이 나옵니다.

 

그냥 기본자료형으로 받았을 때에는 num2가 누구를 참조하는 것이 아닌 num1의 값을 받아서 2+1=3, 3의 값을 가지는 

변수가 되어서 +3을 하면 6이 되어 나옵니다. 참조자가 아니라 그냥 별개의 변수가 되어버리는 겁니다.

반환값이 참조형일 경우는 일반변수로 받든 참조형으로 받든 상관 없지만 이렇게 반환형이 일반형일 경우는 무조건 참조형이 아닌 일반 변수에 저장해야

합니다. 반환값은 일반 상수와 동일하기 때문입니다.

 

 

반대로 매개변수가 일반변수이고 반환형이 참조형이면 어떻게 될까요?

int& Refer(int n)

{

int num=10;

num+=n;

return num;

}

이런 경우 반환형이 참조형이기 때문에 int &val = Refer(5); 함수안의 지역변수 num에 val이라는 또다른 별칭이 생깁니다. 그렇지만 함수값이 반환되면

지역변수인 num은 사라지기 때문에  쓰레기값으로 계산을 하게 됩니다.

 

 그리고 위에 언급했던 const 참조자의 다른 특징이 있습니다.

const 참조자는 상수도 참조가 가능합니다.

const int &val = 24;

변수만 참조했었는데 상수도 참조하는 이유가 있습니다.

한 행에서만 쓰이고 다음에는 버려지는 리터럴 상수들이 있습니다. 예를들어 int num = 2+3; 여기서 2나 3같은 존재들이지요

이러한 존재들은 다음행으로 넘어가면 사라집니다. 그런데 이런 리터럴 상수들을 참조하면 임시변수라는 것을 생성하게 됩니다.

이러한 임시변수에 저장하게되는거지요. 그럼 참조자는 임시변수를 참조하여 안의 값을 참조하는 형태가 됩니다.

그럼 왜 이렇게까지 상수를 참조하느냐

int Add(const int &num1, const int &num2)

{

return num1+num2;

}

같은 함수를 사용하기 위해섭니다. 이 함수에서 인자를 전달하려고 새로운 함수를 선언한다음 받아서 사용한다는 것은 매우 번거롭습니다.

하지만 상수를 참조하면 그냥

cout<<Add(5, 6)<<endl;

호출하면 됩니다.

만약 이렇게 안한다면

int a =5;

int b =6;

선언 후에 cout<<Add(a,b)<<endl;와 같이 사용하게 되는 겁니다.