달력

4

« 2024/4 »

  • 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

 함수내에서, 값(Value)으로 전달받은 인자(Argument)는 참조(Reference)로 전달받는 인자와 차이가 있다. 참조로 전달받은 인자는 변경이 일어났을 때 본래의 객체도 같이 변경되지만 값으로 전달받은 인자는 그렇지 않다.

 

 

1
2
3
4
5
var integer = 5
func multiply(integer: Int, multiplier: Int) {
    //error, integer is defined as a let.
    integer = integer * multiplier
}
cs

 
 애초에 값으로 전달받은 인자는 상수라서 변경조차 불가능하다. 값으로 전달받은 인자를 함수 내에서 수정하려면, 함수의 매개변수(Parameter)에 'inout'이라는 키워드를 붙이면 가능하다.

 

 

1
2
3
4
5
6
7
var integer = 5
func multiply(integer: inout Int, multiplier: Int) {
    integer = integer * multiplier
}
multiply(integer: &integer, multiplier: 2)
print(integer) //10
 
cs



 매개변수에 inout 키워드가 붙었으니, multiply에는 integer의 참조가 전달된 것일까? 

inout Parameter에 대한 Apple의 설명을 보면 이야기가 좀 다르다.



In-Out Parameters: In-out parameters는 다음과 같이 전달됩니다.
1) 함수가 호출됬을 때, 값으로 전달받은 인자는 복사(Copy)됩니다.

2) 함수 내에서는 복사본이 변경됩니다.

3) 함수가 반환(Return)될 때, 복사본의 값이 본래의 값에 할당(Assign)됩니다.

 

 

 Apple의 설명을 확인하기 위해, 간단한 코드를 작성하면...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var number: Int = 2 {
    didSet {
        print("number was assigned.")
    }
}
 
func function(arg: inout Int) {
    print(number) //2
    arg = 5
    print(number) //2
    arg = 10
}
 
function(arg: &number) //"number was assigned."
 
cs

  

 function 내에서 전달받은 인자를 5로 바꾸어도, number는 변하지 않는다. function이 호출된 다음 number의 didSet이 호출되는 것을 볼 수 있는데, 이것을 통해 function 반환 후 본래의 값에 새 값이 할당된다는 것을 확인할 수 있다.

 

 이것은 참조가 전달된 Call-By-Reference와 다르며, Copy-In Copy-Out 또는 Call-By-Value Result라고 불려진다.

 

 

※ 2023.01.24에 추가된 내용

 Swift Docs에 적혀있는, In-Out Parameters의 Optimization에 따르면 Physical Address에 위치한 변수를 In-Out Parameter의 arg로 전달하면 Call-By-Reference로 동작한다고 적혀있다(Call-By-Reference는 Copy로 인한 Overhead는 없지만 Copy-In Copy-Out의 결과와 동일하다).

 

 Compilier의 Optimization Level도 바꾸어 보고, 코드도 이리저리 수정해가며 테스트를 해보았지만... In-Out Parameter를 정의한 함수에서 Call-By-Reference로 동작하는 것을 확인하는 데에 실패했다. Compiler Optimization 결과에 따라 In-Out Parameter의 동작이 달라질 수 있는 것 같으니, 인위적으로 상황을 재현하는 것은 어려울 것 같다.

 

 Swift Docs에 적힌대로, In-Out Parameter를 사용한 함수를 작성할 때, Call-By-Reference를 고려하지 말고 Copy-In Copy-Out로 동작한다고 생각하고 작성하자.

:
Posted by syjdev