삶의 공유

[C++] Call by reference & Call by Value 본문

Programing/C++

[C++] Call by reference & Call by Value

dkrehd 2020. 11. 9. 21:32
728x90
반응형

#출저 : 열혈 C++프로그래밍(책)

 

Call by reference, Call by Value의 의미를 먼저 살펴보면,

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

Call by value 기반으로 Swap 함수를 구현해보면,

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

int main()
{
    int val1 = 10;
    int val2 = 20;
    SwapByValue(val1, val2);
    cout << "Val1 : " << val1 << endl;
    cout << "Val2 : " << val2 << endl;

컴파일 하면, 값은 바뀌지 않고 val1 = 10, val2 = 20이 된다. 즉, 실제 val1, val2가 넘어가는 것이 아니라 val1, val2를 복사하여 함수로 넘겨주기 때문에 값이 변경되지 않는 것이 아니다. 이게 Call by value의 특징이다.

 

값을 바꾸고자 할때 필요한 것이 Call by reference이다.

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

int main()
{
    int val1 = 10;
    int val2 = 20;
    SwapByValue(&val1, &val2);
    cout << "Val1 : " << val1 << endl;
    cout << "Val2 : " << val2 << endl;
}

이렇게 포인터를 이용하여 Call by reference를 구현하면 val1 = 20, val2 = 10으로 값이 변경 된다.

포인터를 사용하면 함수를 사용 할 때 SwapByValue(&val1, &val2) 처럼 주소를 넘겨주기 위해 &를 써야한다.

 

이거를 쓰기 싫다면, 참조자(&)를 이용한 Call by reference를 구현하면 된다.

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

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

    SwapByRef(val1, val2);
    cout << "Val1 : " << val1 << endl;
    cout << "Val2 : " << val2 << endl;
}

이와 같이 매개변수에 포인터 대신 참조자를 써서 함수를 구현하면 함수 호출 시 참조자를 쓸 필요 없이 Call by reference를 구현할 수 있다.

 

아래는 좀더 이해를 돕기 위해 SwapByRef함수를 호출한 순간의 메모리 공간을 표현 한 것이다.

 

몇가지 문제를 풀어보자

 

1) 인자로 전달된 int형 변수의 값을 1씩 증가 시키는 함수(AddPlus)

2) 인자로 전달된 int형 변수의 부호를 바꾸는 함수(ChangedMos)

void AddPlus(int &num1)
{
    ++num1;
}

void ChangedMos(int &num1)
{
    num1 = -1 * num1;
}

int main()
{
    int val1 = 0;

    for(int i = 0; i < 10; i++)
    {
        AddPlus(val1);
    };
    cout << "val1 : " << val1 << endl;

    ChangedMos(val1);
    cout << "val1 : " << val1 << endl;
}

3) 아래 코드를 보면 ptr1, ptr2가 각각 num1, num2를 가리키고 있다. 이 때 ptr1, ptr2를 대상으로 SwapPointer(ptr1, ptr2)로 함수를 호출하고 나면 ptr1, ptr2가 각각 가르키는 대상이 서로 바뀌도록 함수를 정의 해보자

int main()

{

        int num1 = 5;

        int *ptr1 = &num1;

        int num2 = 10;

        int *ptr2 = &num2;

}

 

이렇게 구현하게 되면 함수 상에서는 바뀐것 처럼 보이나, 결론적으로는 바뀌지 않았다. 그 이유는 호출시 ptr1, ptr2를 복사해서 넘겨주는 구문으로 되어 있기 때 문이다.

void SwapPointer(int *ptr1, int *ptr2)
{
    cout << ptr1 << "/" << *ptr1 << endl;
    ptr1 = ptr2;
    cout << ptr1 << "/" << *ptr1 << endl;
}


int main()
{
    int num1 = 5;
    int *ptr1 = &num1;

    int num2 = 10;
    int *ptr2 = &num2;
    cout << "ptr1 : " << ptr1 << "/" << *ptr1 << endl;
    cout << "ptr2 : " << ptr2 << "/" << *ptr2 << endl;
    SwapPointer(ptr1, ptr2);
    cout << "ptr1 : " << ptr1 << "/" << *ptr1 << endl;
    cout << "ptr2 : " << ptr2 << "/" << *ptr2 << endl;
}

(실행한 결과)

ptr1 : 0x7ffee495370c/5
ptr2 : 0x7ffee4953708/10
0x7ffee495370c/5
0x7ffee4953708/10
ptr1 : 0x7ffee495370c/5
ptr2 : 0x7ffee4953708/10

 

SwapPointer 함수 매개변수를 조금 수정해야한다.

이렇게 &를 붙여서 매개변수를 받아야 주소를 받아와서 변경할 수 가있게 된다.

void SwapPointer(int *(&ptr1), int *(&ptr2))
{
    cout << ptr1 << "/" << *ptr1 << endl;
    ptr1 = ptr2;
    cout << ptr1 << "/" << *ptr1 << endl;
}


int main()
{
    int num1 = 5;
    int *ptr1 = &num1;

    int num2 = 10;
    int *ptr2 = &num2;
    cout << "ptr1 : " << ptr1 << "/" << *ptr1 << endl;
    cout << "ptr2 : " << ptr2 << "/" << *ptr2 << endl;
    SwapPointer(ptr1, ptr2);
    cout << "ptr1 : " << ptr1 << "/" << *ptr1 << endl;
    cout << "ptr2 : " << ptr2 << "/" << *ptr2 << endl;
}

(실행한 결과)

ptr1 : 0x7ffee91ad71c/5
ptr2 : 0x7ffee91ad70c/10
0x7ffee91ad71c/5
0x7ffee91ad70c/10
ptr1 : 0x7ffee91ad70c/10
ptr2 : 0x7ffee91ad70c/10

 

 

반응형

'Programing > C++' 카테고리의 다른 글

[C++] 코딩 테스트 개 문제 풀이  (0) 2021.01.17
[C++] 코딩테스트 준비(백준, 고양이문제)  (0) 2021.01.14
[C++]참조자(Reference) 정의  (0) 2020.11.02
C++ 자료형 bool  (0) 2020.10.26
[C++]namespace(이름 공간)  (0) 2020.10.21