ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Call by reference(참조에 의한 호출)와 Call by value(값에 의한 호출)
    C# 2023. 3. 7. 18:32

    함수 호출 방법은 프로그래밍에서 중요한 개념 중 하나입니다. C#에서는 매개변수 전달 방식으로 Call by value Call by reference 두 가지 방식을 지원합니다. 이번 글에서는 Call by reference와 Call by value에 대해 각각 설명하고 예시 코드를 통해 비교해보겠습니다.


    Call by value(값에 의한 호출)

     

    Call by value는 함수 호출 시 인자의 값을 복사하여 함수에 전달합니다. 함수 내부에서 매개변수의 값을 변경해도 호출자에게는 영향을 주지 않습니다. 이는 매개변수의 값이 함수 내부에서만 사용되기 때문입니다.

     

    예시 코드:

    class Program {
        static void AddOne(int x) {
            x++;
        }
    
        static void Main(string[] args) {
            int x = 1;
            AddOne(x);
            Console.WriteLine("x: " + x);  // 출력: 1
        }
    }

     

    위 코드에서 AddOne 메서드는 int 값을 매개변수로 받아 값을 1 증가시키는 메서드입니다. Main 메서드에서 AddOne(x) 코드로 x 변수를 전달하면, x 변수의 값은 1로 유지됩니다. 이는 int 값이 Call by value로 전달되기 때문입니다.

     


    Call by reference(참조에 의한 호출)

    Call by reference는 함수 호출 시 인자의 참조(메모리 주소)를 전달합니다. 함수 내부에서 매개변수의 값을 변경하면 호출자에게도 영향을 줍니다. 이는 매개변수의 값이 메모리에 저장된 위치를 참조하기 때문입니다.

     

    예시 코드:

    class Program {
        static void Swap(ref int a, ref int b) {
            int temp = a;
            a = b;
            b = temp;
        }
    
        static void Main(string[] args) {
            int a = 1;
            int b = 2;
            Swap(ref a, ref b);
            Console.WriteLine("a: " + a);  // 출력: 2
            Console.WriteLine("b: " + b);  // 출력: 1
        }
    }

     

    위 코드에서 Swap 메서드는 ref 키워드를 사용하여 두 개의 int 값을 참조에 의한 호출로 전달받습니다. Main 메서드에서 Swap(ref a, ref b) 코드로 a 변수와 b 변수의 참조를 전달하면, Swap 메서드에서 ab 값을 교환하여 a 변수와 b 변수의 값이 서로 바뀝니다. 이는 int 값이 Call by reference로 전달되기 때문입니다.

     


    Call by reference와 Call by value 비교

    Call by reference와 Call by value는 서로 다른 방식이기 때문에 이들을 비교하려면, 예시로 사용할 수 있는 값과 참조를 비교해야 합니다. 대표적인 예시로는 기본 자료형 변수와 객체 변수를 비교할 수 있습니다.

    • 기본 자료형 변수: Call by value가 사용됩니다. 함수에서 매개변수의 값을 변경해도 호출자에게는 영향을 주지 않습니다.
    • 객체 변수: Call by reference가 사용됩니다. 함수에서 매개변수의 값을 변경하면 호출자에게도 영향을 줍니다.

    예시 코드:

    class Program {
        static void AddOne(int x) {
            x++;
        }
    
        static void Swap(ref int a, ref int b) {
            int temp = a;
            a = b;
            b = temp;
        }
    
        static void UpdateName(Person person) {
            person.Name = "John Doe";
        }
    
        static void Main(string[] args) {
            int x = 1;
            AddOne(x);
            Console.WriteLine("x: " + x);  // 출력: 1
    
            int a = 1;
            int b = 2;
            Swap(ref a, ref b);
            Console.WriteLine("a: " + a);  // 출력: 2
            Console.WriteLine("b: " + b);  // 출력: 1
    
            Person person = new Person("Jane Doe");
            UpdateName(person);
            Console.WriteLine("person.Name: " + person.Name);  // 출력: John Doe
        }
    }
    
    class Person {
        public string Name { get; set; }
    
        public Person(string name) {
            Name = name;
        }
    }

    위 코드에서 AddOne 메서드는 int 값을 매개변수로 받아 값을 1 증가시키는 메서드입니다. Main 메서드에서 AddOne(x) 코드로 x 변수를 전달하면, x 변수의 값은 1로 유지됩니다. 이는 int 값이 Call by value로 전달되기 때문입니다.

     

    Swap 메서드는 ref 키워드를 사용하여 두 개의 int 값을 참조에 의한 호출로 전달받습니다. Main 메서드에서 Swap(ref a, ref b) 코드로 a 변수와 b 변수의 참조를 전달하면, Swap 메서드에서 a와 b 값을 교환하여 a 변수와 b 변수의 값이 서로 바뀝니다. 이는 int 값이 Call by reference로 전달되기 때문입니다.

     

    UpdateName 메서드는 Person 객체를 매개변수로 받아 Name 속성의 값을 변경하는 메서드입니다. Main 메서드에서 UpdateName(person) 코드로 person 변수를 전달하면, UpdateName 메서드에서 person.Name 값을 "John Doe"로 변경합니다. 이후 Main 메서드에서 person.Name 값을 출력하면 "John Doe"가 출력되는데, 이는 Person 객체가 Call by reference로 전달되었기 때문입니다.

     


    Call by reference와 Call by value는 서로 다른 방식이기 때문에 함수를 정의할 때 매개변수를 어떻게 전달할 것인지를 고려하여 함수를 작성하는 것이 중요합니다. 기본 자료형 변수는 Call by value를 사용하며, 객체 변수는 Call by reference가 필요할 수 있습니다. 따라서 함수를 정의할 때 매개변수를 어떻게 전달할 것인지를 고려하여 함수를 작성하는 것이 좋습니다.

     

    Call by value는 함수에서 매개변수 값을 변경하더라도 호출자에게는 영향을 주지 않기 때문에 부작용이 적습니다. 하지만 Call by reference는 함수에서 매개변수 값을 변경하면 호출자에게도 영향을 주기 때문에 부작용이 있을 수 있습니다. 따라서 매개변수 값을 변경하는 일이 없거나 부작용이 없는 경우에는 Call by value를 사용하는 것이 좋습니다.

     

    하지만 객체를 다룰 때는 Call by reference가 필요할 수 있습니다. 이는 객체의 값을 복사하는 것이 아니라 객체의 참조를 전달하기 때문입니다. 객체를 복사하는 것은 메모리 공간을 낭비할 수 있기 때문에 객체를 다룰 때는 Call by reference를 사용하는 것이 효율적입니다.

     

    마지막으로, C#에서는 ref 키워드를 사용하여 값을 전달할 때 Call by reference를 사용할 수 있습니다. ref 키워드를 사용하면 값이 아닌 메모리 주소를 전달하기 때문에 Call by reference와 유사한 효과를 얻을 수 있습니다. 따라서 함수를 작성할 때 매개변수 전달 방식을 고려하여 함수를 작성하는 것이 좋습니다.

     

    ASCII Art로 Call by value와 Call by reference를 비교한 예시:

    Call by value
    
       Main()    x=2
         |
         |
        AddOne(x)
         |
         |
        x=3  --|-- (호출자에게 영향 없음)
              |
              |
            출력: 2
    
    
    Call by reference
    
       Main()    p.name="John"
         |
         |
        UpdateName(p)
         |
         |
      p.name="Jane" --|-- (호출자에게 영향 있음)
                      |
                      |
                  출력: John

    댓글

Designed by Tistory.