C++ Chapter 7.2 : 인수 전달 (값에 의한, 참조에 의한, 주소에 의한)

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


chapter 7. 함수

1. 값에 의한 인수 전달

void func(int x) 
{
    x = 20;
}
int main()
{
    int a = 0;
    func(a); 
    cout << a << endl; // 0 출력
}

func(a) 함수 호출시 내부적으로 int x = a 가 실행된다.

  • 함수의 지역변수이자 매개변수인 int x 에 a의 값이 복사된다.
    • 따라서 func(a) 함수 호출이 끝난 후 a의 값은 변함 없이 0이다. x는 단순히 a의 값을 복사 하여 가져간 것일 뿐이므로.
  • 인수의 값이 복사되어 매개변수에게 넘겨지는 것을 값에 의한 인수 전달 (call by value) 라고 한다.


2. 참조에 의한 인수 전달

  • 함수를 통해 인수(argument)의 값을 바꾸고 싶을 때 사용한다.
  • C와 C++은 리턴을 하나 밖에 못하기 때문에 인수로 넘길 여러 value들을 함수를 통해 변경하고 싶다면 이렇게 포인터 혹은 참조를 통해 인수로 전달한다.
void func(int & x) 
{
    x = 20;
}
int main()
{
    int a = 0;
    func(a); 
    cout << a << endl; // 20 출력
}

func(a) 함수 호출시 내부적으로 int & x = a 가 실행된다.

  • 참조 변수 xmain의 a변수의 별명이 되어 a의 메모리를 공유하게 된다.
    • func(a) 함수 호출이 끝난 후 a의 값은 20으로 바뀐다.
    • x는 a의 메모리를 고유하므로 x = 20 하면 a의 값 또한 20으로 바뀌기 때문에.
  • x의 주소와 a의 주소는 같다.
  • x는 지역 변수이므로 함수 func 안에서만 a의 별명으로 역할을 한다.

주의 사항

void func1(int & x) 
{
    cout << x << endl;
}
void func2(const int & x) 
{
    cout << x << endl;
    x = 20; // ❌ 안됨. x는 const 한 참조변수이므로 값을 변경할 수 없다.
}

int main()
{
    int a = 0;

    func1(6); // ❌ 안됨. 6은 리터럴 상수로 R-value이다.
    func1(a); // ⭕ 가능

    func2(6); // ⭕ 가능
    func1(a); // ⭕ 가능
}
  • 일반 & 참조 변수는 L-value만 참조 가능하다.
    • 즉 메모리 공간이 제대로 잡혀있는 L-value 의 별명만 될 수 있다.
  • const & 참조 변수는 L-value, R-value 모두 참조 가능하다.
    • const가 붙었기 때문에 참조하는 대상의 값을 변경할 수는 없다.

포인터에 대한 참조

void func(int *& ptr)
{
    cout << ptr << endl;
}
int main()
{
    int x = 5;
    int * ptr_x = &x;

    func(ptr_x);
}

매개변수가 *& 타입인 것에 주목하기! 이는 곧 (int *) & ptr이나 마찬가지다. ptrint * 포인터 타입의 참조변수인 것.

  • ptr_xptr은 같은 메모리를 공유한다. (서로 주소가 같음)
    • ptr 값이 함수 내에서 바뀌면 ptr_x 의 값도 변한다.

배열에 대한 참조

void func(int (&arr)[4])
{
    for (auto & elements : arr)
      cout << elements << endl;
}
int main()
{
    int array[4] = {1, 2, 3, 4};

    func(array);
}
  • int (&arr)[4] 로 배열을 참조한다.
    • 미리 [크기] 지정 필수 !
  • 함수 호출시 배열 이름만 인수로 넘겨주면 된다. func(array)
void func(vector<int> & arr)
{
    for (auto & elements : arr)
      cout << elements << endl;
}
  • vector 참조 타입시엔 위와 같은 모양


3. 주소(포인터)에 의한 인수 전달

void func(int * ptr)
{
    *ptr = 100;
}
int main()
{
    int value = 5;
    int * ptr_value = &value;

    func(ptr_value); // ⭕ 가능
    func(&value); // ⭕ 가능
    func(5); // ❌ 안됨.
}
  • func의 ptrint * 포인터 타입인 지역변수이자 매개변수다.
  • 참조와 다르게 ptrptr_value는 주소가 다르다. 즉 별개의 변수다.
    • ptr_value는 int 변수인 value의 주소를 담고 있는데 ptr이 ptr_value로부터 해당 value의 주소값을 복사 받은 것 뿐이다. (call by value)
  • 간접 참조로 값을 변경할 수 있다.
    • 함수 안에서 *ptr = 100 해주었기 때문에 ptr이 함수 내부에서 가리키고 있는 value의 값 또한 100으로 바뀐다.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기