Swift Func 的參數預設都是 Call by Value,但透過使用 inout
關鍵字,就可以讓傳入 func 的參數變成 Call by Reference。
Swift Func 的參數預設為 Call by Value
我們直接實作一個用來交換兩個變數值的 Function 來做說明。
func swap(first: Int, second: Int) {
let temp = second
second = first
first = temp
}
這樣的 Func 看似合理,但 Xcode 卻會跟我們說錯:「Cannot assign to value: xxx is a 'let' constant」。
這是因為 Swift Func 的參數預設都是 Call by Value,而且是 let
,代表著傳進 func 裡的值都不能被更動。
Swift 的 Func 能否改用 Call by Reference?
看到這裡,如果以 C 語言的角度來看,可能會想說那能不能改用指標的方式,傳記憶體位置進去,來直接對記憶體位置裡的值做更動。答案是可以的,但不像 C 語言用「* 星號」,Swift 會使用 inout
這個關鍵字。
Swift 語言裡的 inout 關鍵字
當我們希望一個 func 可以直接更動傳進去的變數時,就可以使用 inout 這個關鍵字,它的全名是「copy-in copy-out」,會將參數預設的 Call by Value 改成 Call by Reference,以我們上面的 swap 方法來說,就會希望它能直接更動我們傳進去的兩個變數。
Swift inout 的使用方法
inout 的使用方法很簡單,只要在冒號後方、型別前面加上 inout 就行了:
func swap(first: inout Int, second: inout Int) {
let temp = second
second = first
first = temp
}
呼叫含有 inout 的 Swift func
因為 inout 的行為跟預設的不同,我們也就不能用平常的方式來呼叫含有 inout 的 func,會需要在傳入有 inout 的參數前加上「&」,這跟 C 語言的用法一樣,一方面也能提醒呼叫者,這個 func 有可能會改動到傳進去的變數。
swap(first: &a, second: &b)
Swift inout 的使用限制
因為 inout 會讓 func 直接去訪問某個記憶體位置,為了達到記憶體排他性,有以下的寫法是會報錯的:
不要在 inout func 裡去存取原來傳進來的變數
var someValue: Int
func someFunction(a: inout Int) {
a += someValue
}
someFunction(&someValue)
不要傳同一個變數進不同的 inuot 參數裡
var someValue: Int
func someFunction(a: inout Int, b: inout Int) {
/// Do Something
}
someFunction(&someValue, &someValue)
關於 XcodeProject
XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。