如果在類中使用mutating
關(guān)鍵字鲫趁,編譯器會(huì)報(bào)錯(cuò)'mutating' isn't valid on methods in classes or class-bound protocols
。
因?yàn)轭愂且妙愋痛菏伲Y(jié)構(gòu)體和枚舉是值類型,在值類型的實(shí)例方法中,值類型的屬性默認(rèn)是不可以被修改的夺克。為了修改值類型的屬性值砰蠢,需要在它的實(shí)例方法上使用mutating
關(guān)鍵字。
struct LSStack {
private var items = [Int]()
mutating func push(item: Int) {
items.append(item)
}
}
var s = LSStack()
s.push(item: 1)
上面是一個(gè)簡(jiǎn)單的棧的例子,需要改變值類型LSStack
中屬性items
的值,則需要在push
方法前添加mutating
關(guān)鍵字。
// LSStack.push(item:)
sil hidden @$s4main7LSStackV4push4itemySi_tF : $@convention(method) (Int, @inout LSStack) -> () {
// %0 "item" // users: %5, %2
// %1 "self" // users: %6, %3
bb0(%0 : $Int, %1 : $*LSStack):
debug_value %0 : $Int, let, name "item", argno 1 // id: %2
debug_value_addr %1 : $*LSStack, var, name "self", argno 2 // id: %3
%4 = alloc_stack $Int // users: %5, %11, %9
store %0 to %4 : $*Int // id: %5
%6 = begin_access [modify] [static] %1 : $*LSStack // users: %10, %7
%7 = struct_element_addr %6 : $*LSStack, #LSStack.items // user: %9
// function_ref Array.append(_:)
%8 = function_ref @$sSa6appendyyxnF : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () // user: %9
%9 = apply %8<Int>(%4, %7) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> ()
end_access %6 : $*LSStack // id: %10
dealloc_stack %4 : $*Int // id: %11
%12 = tuple () // user: %13
return %12 : $() // id: %13
} // end sil function '$s4main7LSStackV4push4itemySi_tF'
將上述代碼轉(zhuǎn)為sil
發(fā)現(xiàn)商蕴,push
參數(shù)中除了第一個(gè)顯示的Int
類型參數(shù),還有一個(gè)使用@inout
修飾的LSStack
悲敷,通過(guò)結(jié)構(gòu)體元素地址進(jìn)行修改究恤。
func swap( a: inout Int, b: inout Int) {
let temp : Int = a
a = b
b = temp
}
var a:Int = 10
var b:Int = 20
swap(&a, &b)
print(a)
print(b)
函數(shù)參數(shù)默認(rèn)是不可變,如果想要修改函數(shù)參數(shù)則需要使用inout
進(jìn)行修飾后德,同時(shí)傳參時(shí)需要傳入地址