9. [C++] 참조자(Reference)와 함수

2024. 4. 11. 15:55[C++]/C++ 언어 기초

🍃  Call-by-value & Call-by-reference

Call-by-value          값을 인자로 전달하는 함수의 호출방식
Call-by-reference    주소 값을 인자로 전달하는 함수의 호출방식

 

 

이 중, Call-by-value 기반의 함수는 다음과 같이 정의된 함수를 의미한다.

int Adder(int num1, int num2) {
	return num1 + num2;
}
  • 위 함수는 두 개의 정수를 인자로 요구하고 있다.
  • Call-by-value 형태로 정의된 함수의 내부에서는, 함수외부에 선언된 변수에 접근이 불가능하다.
  • 따라서 두 변수에 저장된 값을 서로 바꿔서 저장할 목적으로 다음과 같이 함수를 정의하면 원하는 결과를 얻을 수 없다.

Call-by-value 기반의 함수

void SwapByValue(int num1, int num2) {
	int temp = num1;
    num1 = num2;
    num2 = temp;
}

 

위의 함수를 대상으로 다음의 main 함수를 실행하면, 출력결과는 다음과 같다.

int main(void) {
    int val1 = 10;
    int val2 = 20;
    SwapByValue(val1, val2);    
    //val1과 val2에 저장된 값이 바뀌기를 기대함
    cout<<"val1: "<<val1<<endl; // 10 출력 
    cout<<"val2: "<<val2<<endl; // 20 출력
    return 0;
}
val1 = 10
val2 = 20
  • 이는 val1과 val2에 저장된 값이 서로 바뀌지 않았음을 의미한다.
  • 그래서 필요한 것이 Call-by-reference 기반의 함수이다.

 

Call-by-reference 기반의 함수

void SwapByRef(int * ptr1, int * ptr2) {
    int temp = *ptr1;
    *ptr1 = *ptr2;
    *ptr2 = temp;
}

위의 함수에서는 두 개의 주소 값을 받아서 주소 값이 참조하는 영역에 저장된 값을 직접 변경하고 있다. 다음의 출력결과를 확인할 수 있다

int main(void) {
	int val1 = 10;
    int val2 = 20;
    SwapByRef(&val1, &val2);    
    //val1과 val2에 저장된 값이 바뀌기를 기대함
    cout<<"val1: "<<val1<<endl; // 20 출력 
    cout<<"val2: "<<val2<<endl; // 10 출력
    return 0;
}
val1 = 20
val2 = 10

 

🍃  Call-by-address? & Call-by-reference!

본래 C언어에서 말하는 Call-by-reference는 다음의 의미를 지닌다.

"주소 값을 전달받아서, 함수 외부에 선언된 변수에 접근하는 형태의 함수호출"

 

C++에서는 함수 외부에 선언된 변수의 접근 방법으로 두 가지가 존재한다.

하나는 '주소 값'을 이용하는 방식, 다른 하나는 ' 참조자'를 이용하는 방식이다.

  • 주소값을 이용한 Call-by-reference
  • 참조자를 이용한 Call-by-reference

이렇듯 C++에서는 두 가지 방식으로 Call-by-reference의 함수정의가 가능하다.

 


 

🍃 참조자를 이용한 Call-by-reference

  • C++에서는 참조자를 기반으로도 Call-by-reference의 함수호출을 진행할 수 있다.
  • Call-by-reference의 가장 큰 핵심은 함수 내에서 함수외부에 선언된 변수에 접근할 수 있다는 것이다.
void SwapByRef2(int &ref1, int &ref2) {
    int temp = ref1;
    ref1 = ref2;
    ref2 = temp;
}
참조자는 선언과 동시에 변수로 초기화되어야 한다면서요!
  • 매개변수는 함수가 호출되어야 초기화가 진행되는 변수들이다.
  • 즉, 위의 매개변수 선언은 초기화가 이뤄지지 않은 것이 아닌, 함수 호출 시 전달되는 인자로 초기화를 하겠다는 의미이다.

 

int main(void) {
    int val1 = 10;
    int val2 = 20;
    SwapByRef2(val1, val2);
    cout<<"val1: " <<val1<<endl;
    cout<<"val2: " <<val2<<endl;
    return 0;
}

  • 매개변수로 선언된 참조자 ref1과 ref2는 main 함수에서 선언된 변수 val1과 val2의 다른 이름이 된다.
  • 그리고 SwapByRef2 함수 내에서는 이 두 참조자를 통해 값의 교환 과정을 거친다.

RefSwap.cpp

#include <iostream>
using namespace std;

void SwapByRef2(int &ref1, int &ref2) {
    int temp =ref1;
    ref1=ref2;
    ref2=temp;
}

int main(void) {
    int val1 = 10;
    int val2 = 20;

    SwapByRef2(val1, val2);
    cout<<"val1: "<<val1<<endl;
    cout<<"val2: "<<val2<<endl;
    return 0;
}
val1: 20
val2: 10

 


문제 풀이

 

문제 1

참조자를 이용해서 다음 요구사항에 부합하는 함수를 각각 정의하여라.
     -> 인자로 전달된 int형 변수의 값을 1씩 증가시키는 함수
     -> 인자로 전달된 int형 변수의 부호를 바꾸는 함수

그리고 위의 각 함수를 호출하여 그 결과를 확인하는 main 함수까지 작성하여라.

 

 

내 풀이

#include "stdafx.h"
#include <iostream>
#include <cstring>

using namespace std;
using namespace System;

void increseNum(int *num1, int *num2)
{
   *num1 += 1;
   *num2 += 1;
}

void reverseNum(int *num1, int *num2){
   *num1 *= -1;
   *num2 *= -1;
}

int main(array<System::String ^> ^args)
{
   int num1,num2;
   cout<<"숫자1 입력 : "; cin>>num1;
   cout<<"숫자2 입력 : "; cin>>num2;

   cout<<"[입력한 숫자]"<<endl<<"숫자1 : "<<num1<<endl<<"숫자2 : "<<num2<<endl;
   increseNum(&num1, &num2);
   cout<<"[1 증가한 숫자]"<<endl<<"숫자1 : "<<num1<<endl<<"숫자2 : "<<num2<<endl;
   reverseNum(&num1, &num2);
   cout<<"[부호 바뀐 숫자]"<<endl<<"숫자1 : "<<num1<<endl<<"숫자2 : "<<num2<<endl;
}

 

 

문제 2

앞서 소개한 예제 RefSwap.cpp의 SwapByRef2 함수를 다음의 형태로 호출하면 컴파일 에러가 발생한다.
SwapByRef2(23, 45);
컴파일 에러가 발생하는 이유가 무엇인지 설명해보자.

 

내 풀이

  • SwapByRef 함수의 매개변수 선언 위치에 참조자가 선언되었다.
  • 참조자는 상수를 참조할 수 없기 떄문에 매개변수의 인자로는 반드시 변수가 등장해야한다.
  • SwapByRef2(23, 45)는 상수로 호출하기 때문에  컴파일 에러가 발생한다.

 

 

문제 3

문제의 제시에 앞서 먼저 다음 코드를 보자.

int main(void) {
    int num1 = 5;
    int ptr1 = &num1;
    int num2 = 10;
    int ptr2 = &num2;
. . . .
}

위의 코드를 보면 ptr1과 ptr2가 각각 num1과 num2를 가리키고 있다. 이 때 ptr1과 ptr2를 대상으로 다음과 같이 함수를 호출하고 나면,

SwapPointer(ptr1, ptr2);

ptr1과 ptr2가 가리키는 대상이 서로 바뀌도록 SwapPointer 함수를 정의해보자.

 

 

내 풀이

#include "stdafx.h"
#include <iostream>
#include <cstring>

using namespace std;
using namespace System;

void SwapPointer(int *ptr1, int *ptr2){
	int temp = *ptr1;
	*ptr1 = *ptr2;
	*ptr2 = temp;
}

int main(array<System::String ^> ^args)
{
	int num1 = 5;
	int *ptr1 = &num1;
	int num2 = 10;
	int *ptr2 = &num2;

	SwapPointer(ptr1, ptr2);

	cout<<"값 : "<<*ptr1<<"   "<<*ptr2<<endl;

}

 

반응형