iOS/Swift

Swift) inout 파라미터

Dev.Andy 2024. 4. 10. 20:30

머리말

Swift는 다른 언어와 다르게 함수의 파라미터가 상수여서 파라미터의 값을 변경하려면 "inout"이라는 키워드를 사용해야 한다. 우리말로 하면 "출입"이라는 키워드일텐데 도대체 이 키워드는 무엇인지 살펴 보자.

 

본문

공식문서의 inout

한번 공식문서에서 inout을 살펴 보자

In-Out Parameters in Functions

You write an in-out parameter by placing the inout keyword right before a parameter’s type. An in-out parameter has a value that’s passed in to the function, is modified by the function, and is passed back out of the function to replace the original value. For a detailed discussion of the behavior of in-out parameters and associated compiler optimizations, see In-Out Parameters.

in-out 파라미터는 파라미터의 타입 바로 전에 inout 키워드를 작성한다. in-out 파라미터는 함수로 전달하는 값을 가지고 있고 함수로 부터 이 값을 수정하고 원래 값을 대체하기 위해 함수 밖으로 다시 되돌린다. In-out 파라미터와 컴파일러 최적화의 동작에 대한 자세한 설명은 In-Out 파라미터 (In-Out Parameters)를 참고.

In-Out Parameters - Functions | Swift Documentation

 

코드 예시

두 정수를 교환하는 함수

아래 코드를 확인해 보자.

inout 키워드를 파라미터로 사용하고, 앰퍼샌드라 불리는 `&` 기호를 아규먼트에 사용하여 할당한 두 변수의 값을 바꾸는(재할당하는) 함수이다.

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
	let temp = a
	a = b
	b = temp
}

var someInt = 92
var anotherInt = 30
swapTwoInts(&someInt, &anotherInt) // someInt = 30, anotherInt = 92

 

inout과 `&`가 없다면?

만약 inout과 `&`를 제외하고 코드를 작성하면 파라미터가 상수이기에 에러가 발생한다.

func swapTwoInts(_ a: Int, _ b: Int) {
	let temp = a
	a = b            // 🔥 error: cannot assign to value: 'a' is a 'let' constant
	b = temp         // 🔥 error: cannot assign to value: 'b' is a 'let' constant
}

var someInt = 92
var anotherInt = 30
swapTwoInts(someInt, anotherInt)

 

inout의 과정

inout 파라미터의 과정을 살펴 보자

과정 (copy-in copy-out)

  1. 함수 호출 시 파라미터의 변수에 대한 복사가 이루어진다.
  2. 함수 스코프 안에서, 복사한 변수의 값을 수정한다.
  3. 함수가 반환(return) 될 때, 변화된 값을 원본의 변수에 재할당한다.

이러한 과정을 copy-in copy-out라 부르는데 이를 줄여 Swif에서는 "inout"이라는 키워드로 이를 사용한다.

변수 앞에 붙는 주소 연산자, 앰퍼샌드(&)

in-out 파라미터로 변수만 전달할 수 있다. 상수와 리터럴은 수정할 수 없기 때문에 인수로 상수 또는 반복 값은 전달할 수 없다. 함수에 수정 가능함을 알리기 위해 in-out 파라미터에 인수로 전달할 때 변수의 이름 앞에 주소 연산자인 ampersand(앰퍼샌드; &)를 붙인다.

주소 연산자는 `&`를 실제 할당할 변수 앞에 써서 그 변수의 시작 주소를 할당하기 위해 쓴다. C언어의 포인터 개념에서 등장하면 쉽게 접할 수 있다.