참조로 전달

Jaemyeong Lee·2024년 8월 8일
0

FastCampusC++

목록 보기
42/78

C++ 참조로 전달 예제: 자세한 설명

이 포스트에서는 C++에서 참조를 사용하여 값을 전달하는 방법에 대해 설명합니다. 참조를 통해 함수 내에서 원본 데이터를 수정하고 효율성을 높이는 다양한 예제를 살펴보겠습니다.

예제 1: 참조를 사용한 스왑 함수

void swap0(int& px, int& py)
{
    int temp = px;
    px = py;
    py = temp;
}

설명:

  • swap0 함수는 두 정수를 참조로 받아 값을 교환합니다.
  • pxpyxy의 별칭이므로, 함수 내에서 pxpy를 변경하면 xy의 값이 변경됩니다.

예제 2: 참조를 사용한 스왑 함수 호출

int main()
{
    {
        int x = 10, y = 20;
        swap0(x, y);

        cout << x << endl;       // 20
        cout << y << endl;       // 10
    }

    {
        int x = 10, y = 20;
        // swap0(x, y); 풀어쓰기

        int& px = x;
        int& py = y;

        int temp = px;
        px = py;
        py = temp;

        cout << x << endl;       // 20
        cout << y << endl;       // 10
    }
}

설명:

  • 첫 번째 블록에서는 swap0 함수를 호출하여 xy의 값을 교환합니다.
  • 두 번째 블록에서는 swap0 함수의 동작을 수동으로 수행합니다. pxpyxy의 참조입니다. 이를 통해 값을 교환합니다.

예제 3: 구조체 참조를 사용한 수정 및 출력

struct Weapon
{
    int price;
    int power;
};

void upgrade(Weapon& weapon)
{
    weapon.power += 10;
    weapon.price += 10;
}

void print(const Weapon& weapon)
{
    cout << weapon.power << endl;
    cout << weapon.price << endl;
}

설명:

  • Weapon 구조체는 pricepower 필드를 가집니다.
  • upgrade 함수는 Weapon 참조를 받아 powerprice를 수정합니다.
  • print 함수는 Weapon의 const 참조를 받아 값을 출력합니다. const 참조는 함수 내에서 값을 변경할 수 없음을 보장합니다.

예제 4: 참조를 사용한 구조체 수정 및 출력

int main()
{
    {
        Weapon weapon{10, 20};
        upgrade(weapon);
        print(weapon);           // 30 20
    }
}

설명:

  • upgrade 함수를 호출하여 weaponpowerprice를 증가시킵니다.
  • print 함수를 호출하여 수정된 weapon의 값을 출력합니다.

예제 5: 참조를 사용한 값 설정

int main()
{
    {
        int num;
        cin >> num; // num을 레퍼런스로 넘겨주기 때문에 scanf처럼 num의 주소로 넘겨주지 않아도 된다
    }
}

설명:

  • cinnum을 참조로 받아 사용자로부터 입력받은 값을 설정합니다. 참조를 사용하므로 주소를 명시적으로 전달할 필요가 없습니다.

예제 6: 참조를 사용한 배열 수정

int main()
{
    {
        int nums[] = {1, 2, 3, 4};
        for (int num : nums)
        {
            num = 0; // nums의 값이 안 바뀐다
        }

        for (int& num : nums)
        {
            num = 0; // nums의 값이 바뀐다
        }

        for (const int& num : nums)
        {
            // num = 0; // nums의 값을 바꿀 수 없다. 레퍼런스로 넘겼기 때문에 성능에 유리하다
        }
    }
}

설명:

  • 첫 번째 루프에서는 num이 값으로 전달되므로 nums 배열의 값이 변경되지 않습니다.
  • 두 번째 루프에서는 num이 참조로 전달되므로 nums 배열의 값이 0으로 변경됩니다.
  • 세 번째 루프에서는 num이 const 참조로 전달되므로 값을 변경할 수 없습니다. 이는 성능상 이점을 제공합니다.

예제 7: 참조와 상수 참조를 사용한 함수 호출

int squarev(int value)
{
    return value * value;
}

int squaref(const int& ref)
{
    return ref * ref;
}

int main()
{
    {
        int x = 10;
        cout << squarev(10.1) << endl;

        // 상수 참조는 호환이 되는 타입은 임시 객체를 생성해서 가리키게 한다.
        // 이 경우 10.1은 double 형이고 squaref의 ref는 const int& 이기 때문에
        // 10 임시 객체가 만들어진다.
        // 상수 참조 타입은 최대한 일반 값 타입과 호환이 되도록 하고 싶은 의도
        cout << squaref(10.1) << endl;
    }
}

설명:

  • squarev 함수는 정수를 값으로 받아 제곱을 반환합니다.
  • squaref 함수는 정수를 const 참조로 받아 제곱을 반환합니다.
  • squarev 호출 시 10.1int로 변환되어 100을 반환합니다.
  • squaref 호출 시 10.1double 타입이지만, const 참조는 호환되는 타입을 임시 객체로 생성하여 가리키므로 10 임시 객체가 생성되어 제곱된 값을 반환합니다.

예제 8: 위험한 반환 참조 및 구조체 참조 반환

int& func0()
{
    int num = 0;
    return num; // 위험하다. num은 삭제 됨
}

int& func1(Weapon& weapon)
{
    return weapon.power;
}

int main()
{
    {
        Weapon weapon{10, 20};
        func1(weapon) = 30; // 이런 것도 된다
    }
}

설명:

  • func0 함수는 지역 변수 num의 참조를 반환합니다. 이는 위험합니다. 함수가 종료되면 num은 삭제되므로 참조가 유효하지 않습니다.
  • func1 함수는 Weapon 구조체의 power 필드의 참조를 반환합니다. 이를 통해 main 함수에서 power를 직접 수정할 수 있습니다.

결론

C++에서 참조를 사용하면 함수 내에서 원본 데이터를 효율적으로 수정할 수 있습니다. 참조를 사용하면 포인터처럼 주소를 명시적으로 전달하지 않아도 되며, 코드가 간결해지고 가독성이 높아집니다. const 참조를 사용하면 값의 수정이 불가능하도록 하여 안전성을 높일 수 있습니다. 이러한 참조 전달 방식을 이해하는 것은 C++ 프로그래밍에서 매우 중요합니다.

profile
李家네_공부방

0개의 댓글