티스토리 뷰

프로그래밍

C#의 Pass by value

merit nada 2021. 2. 14. 16:24

저번 포스팅을 통해 C#Value Type(값 형식)Reference Type(참조 형식)에 대해서 알아보았습니다.

 

각 타입 변수에 대입 연산자(=)를 사용했을 때 나타나는 동작 차이를 통해

두 타입이 어떻게 근본적으로 다른지 알아보았죠.

 

이번 포스팅에서는 각 타입을 함수의 Argument로 보냈을 때 나타나는 동작 차이에 대해 알아보겠습니다.

그리고 그 외에 헷갈릴 수 있는 부분인 Pass by valuePass by reference에 대해 알아보겠습니다.

 

용어 때문에 혼동될 수 있지만 Pass by valuePass by reference

인자로 보내는 변수가 "Value Type이냐, Reference Type이냐" 와는 상관이 없습니다.

 

Value TypePass by value로 보낼 수도 Pass by reference로 보낼 수도 있고

Reference TypePass by value로 보낼 수도 Pass by reference로 보낼 수도 있습니다.

 

미리 이야기하면 Pass by valuePass by reference를 구분하는 것은

in, out, ref라는 키워드를 넣냐 혹은 넣지 않냐의 차이입니다.

세 키워드 모두 없다면 Pass by value이고 세 키워드 중 하나가 있으면 Pass by reference입니다.

이 세 키워드는 동시에 같은 Parameter에 존재할 수 없습니다.

 

Pass by value (Value Type)

일단 기본적으로 함수를 정의하고 호출하면 Pass by value로 진행이 됩니다.

C#이 신기한 점이 이 모든 것을 잘 모른채 신경쓰지 않고 코딩해도

어느 정도 의도대로 동작하며 효율 또한 나쁘지 않다는 것입니다.

 

먼저 코드를 봅시다.

Person Class
 Pass by value

위와 같은 코드가 있을 때 결과가 어떻게 나올까요?

직접 해보시면 아시겠지만 결과는

30

25

입니다.

 

num 변수는 ValueFunc을 호출하고 나서 값이 변하지 않았고

person 변수는 ReferenceFunc을 호출하고 나서 값이 변했죠.

 

C++을 처음 언어로 배운 사람이라면 "Pass by value는 함수 호출 후 값이 안 변하고

Pass by reference는 함수 호출 후 값이 변할 수 있다."라고 기억하실 수도 있습니다.

 

위 예제를 보면 person 변수는 값이 변했습니다.

그렇다면 이것은 Pass by reference일까요?

정답은 당연히 아닙니다.

이런 결과가 나온 이유는 Value TypeReference Type의 차이 때문에 발생한 것입니다.

 

함수 정의

위와 같은 함수가 있을 때

값을 Argument로 보내는 것을 아래와 같이 풀어서 해석하면 좀 더 쉽게 이해할 수 있습니다.

함수 호출 예시

위 예제를 보시면 a라는 인자를 받는 함수 ValueFunc(int a)를 만들어 두었습니다.

함수 본문에서는 a += 10; 라는 구문을 작성했죠

만약 ValueFunc(num); 이런 식으로 함수를 호출하면

num에 담긴 값이 a로 넘어가고 그 후에 함수 본문 a += 10; 이 호출될 것입니다.

 

하지만 이렇게 함수에 값을 넘기는 부분은 사실 일종의 대입 연산자(=)가 내부적으로 작동한 것처럼 볼 수 있습니다.

 

// 함수 호출을 통한 값 전달이라고 되어 있는 부분은 사실

// 함수 호출 없이 값 전달과 거의 동일한 동작을 한다고 볼 수 있는 것이지요.

 

함수 본문이 실행되기 전 int a라는 변수를 만들고 그곳에 인자로 보낸 num이라는 값을 대입한 것입니다.

이렇게 해석할 경우 함수 본문에서 a 값이 바뀌었을 때 num 값이 바뀌지 않은 것이 이해가 됩니다.

 

저번 포스팅에서 설명했듯이 anum은 애초에 다른 메모리 공간을 뜻하기 때문에

하나의 값이 바뀐다고 해도 영향을 받지 않죠.

 

여러 개의 Parameter가 있어도 똑같습니다.

여러 개의 Parameter

함수 본문 위에 각 Parameter 변수를 생성하는 부분과

Argument로 받은 값을 대입하는 부분이 생략되어 있다고 생각해도 되는 것입니다.

 

여기서 단 하나 주의할 점은

함수 Parameter로 정의된 변수 이름과 Argument로 보낸 변수 이름이 같을 수도 있다는 것입니다.

단, 실제로 뜻하는 메모리 공간은 다릅니다.

 

예를 들어

함수 정의
함수 호출

위와 같이 정의하고 호출했을 때 a라는 이름의 변수는 프로그래머에게만 똑같이 보일 뿐

실제로 컴퓨터에게는 전혀 다른 메모리 공간으로 취급합니다.

 

Pass by value (Reference Type)

다음으로는 Reference Type 변수를 Pass by value로 보냈을 때의 상황을 알아보겠습니다.

사실 앞서 설명한 2가지만 기억하면 이 부분을 이해하는 것은 껌입니다.

1. Value Type과 Reference Type의 대입 연산자(=) 동작 차이

2. 함수 Parameter로 값을 보내는 것의 의미

 

함수 Parameter로 값을 보내는 것의 의미를 Reference Type 버전으로 다시 한 번 살펴봅시다.

함수 호출 예시

처음에 person 객체를 생성하고 person.strength 값을 20으로 설정합니다.

ReferenceFunc(person); 은 결국 아래에 작성한

// 함수 호출 없이 값 전달

부분과 거의 동일하게 동작하게 됩니다.

이 구문이 실행되고 나면 person.strength의 값이 바뀐 것이 이해가 될 것입니다.

Person p = person; 을 통해 pperson은 같은 객체를 가리키게 되었고

객체에 대한 값 수정은 모두에게 적용이 됩니다.

 

결론

지금까지 C#Pass by value에 대해서 알아보았습니다.

사실 앞서도 설명했지만 Pass by value만 사용해서 코딩해도 크게 문제가 되지는 않습니다.

단, 특이한 경우에 Pass by reference가 필요할 때가 있습니다.

 

예를 들자면

1. 커다란 Struct 변수를 함수 인자로 보내고 싶은데 메모리 복사하는 연산이 부담스러울 때

2. 어떤 Referece Type 변수의 생성을 함수 안에서 해야할 때 (string 변수에서 특히 많이 발생)

3. 함수로부터 여러 타입의 리턴 값을 받고 싶을 때

입니다.

 

따라서 C#을 제대로 활용하려면 Pass by reference에 대해서 아는 것이 좋습니다.

다음 시간에는 Pass by reference 개념과 구현하기 위해 꼭 필요한 키워드인 ref, in, out에 대해서 알아보겠습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함