Swift

2024 年 4 月 14 日

讓 Swift Func Call by Reference 的 inout

已複製到剪貼板


Swift Func 的參數預設都是 Call by Value,但透過使用 inout 關鍵字,就可以讓傳入 func 的參數變成 Call by Reference。

Swift Functions
Swift Functions

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」。

Xcode Warning:Cannot assign to value: xxx is a 'let' constant
Xcode Warning: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)

分享文章

已複製到剪貼板

主題文章

查看 Swift

超級感謝

關於 XcodeProject

XcodeProject 創立於 2023,致力於協助開發者探索 Apple 的創新世界,學習在 iOS、iPadOS、macOS、tvOS、visionOS 與 watchOS 上開發 App,發現眾多技術與框架,讓開發者獲得更多能力。


Contacts

Ricky Chuang

XcodeProject

RickyChuang.xcodeproj@gmail.com

XcodeProject 聯絡

contact.xcodeproj@gmail.com

最新文章