iOS Swift 函数的输入输出参数(关键字 inout)

在 Swift 中,输入输出函数(In-Out 参数)允许函数对传入的变量进行修改,并且这些修改会在函数调用后反映在原始变量上。通常,函数的参数是常量,无法在函数内部修改传递进来的变量,而 In-Out 参数可以改变这一行为。

In-Out 参数的语法和用法:

     使用 inout 关键字:

        在函数定义时,将参数声明为 inout 类型,表示该参数的值可以在函数内部修改,并且修改会影响到原始变量。

    调用时需要使用 &

        当你调用一个接受 inout 参数的函数时,需要在传递参数时使用 & 符号,表示传递的是变量的引用,而不是值。

var n = 5 //这里需要用 必须用var 来声明 因为必须是变量 不能是常量 也不能是字面量
func sum(_ num :inout Int) {//inout 关键字将参数num 声明为输入输出参数
    num = num + 1 
}
sum(&n)  //& 用来明确标记这个方法的调用是输入输出参数的函数 里面会对这个n 进行修改 
print(n) //n 是 6

注意事项:

  •      In-Out 参数不能是常量:传递给 In-Out 参数的必须是变量,不能是常量或字面量。
  •     In-Out 参数会改变原始值:这意味着函数内部对 In-Out 参数的修改会直接影响外部传递的变量。
  •     安全性:在函数结束之前,传入的变量的值不能被其他操作影响。

适用场景:

  •     交换两个变量的值:如上例所示,使用 In-Out 参数可以很方便地交换两个变量的值。
  •     累加或减少某个值:在需要修改多个变量时可以使用 In-Out 参数。
  •     更改传递进来的数据:某些场景下你可能需要传递一个对象或数据,并在函数内部修改它。

安全性的理解:

In-Out 参数的安全性问题主要与多线程环境下的访问、不可变性以及变量生命周期等有关。 

1. 防止数据竞争和不一致性

In-Out 参数的机制是将变量的引用传递给函数,这意味着函数直接操作外部变量。如果在多线程环境下,多个线程同时访问或修改同一个变量,会引发数据竞争(Data Race)问题。为避免这种情况,Swift 对 In-Out 参数有一些限制,以提高安全性:

  • 值拷贝行为:在函数执行时,Swift 会对 In-Out 参数进行临时拷贝,函数执行完毕后再将修改后的值赋回原始变量。这种机制可以避免在函数内部处理参数时,对该参数的其他操作产生冲突。

  • 限制可变性:传递给 In-Out 参数的变量必须是变量(var),而不能是常量(let)。这确保了参数在传递前具有可变性。

2. 禁止常量和字面量的修改

In-Out 参数不能传递常量或字面量,这是 Swift 设计中对数据安全的一种保障。具体体现在:

  • 常量保护:如果你尝试传递常量或字面量给 In-Out 参数,编译器会报错。这防止了意外修改不应被修改的数据。

    例如,以下代码会导致编译错误,因为 a 是常量:

let a = 10
var b = 20
swapTwoInts(&a, &b) //常量保护 编译错误:Cannot pass immutable value 'a' as inout argument

 func changeValue(_ value: inout Int) {
   value += 10
 }

  changeValue(&5) // 常量保护 编译错误:Cannot pass immutable value '5' as inout argument

3. 控制变量的生命周期,避免并发访问问题

In-Out 参数的使用还涉及到变量的生命周期安全:

  • 引用的时间限制:传递给 In-Out 参数的变量在函数调用时,会被临时锁定为不可访问的状态,直到函数执行完毕,防止函数内外对该变量进行并发访问。

    这保证了变量在传入函数时不会被其他代码修改,从而防止数据不一致问题。

4. 显式修改,避免隐式副作用:关键符号 &

In-Out 参数的修改是显式的,也就是说,在调用 In-Out 参数函数时,必须通过 & 符号来表明该参数是可修改的。这样设计可以提高代码的可读性和可维护性,因为开发者很清楚哪些参数会被修改,不写就会编译报错

5. 编译器的静态检查,防止多个 In-Out 参数修改同一变量

func changeValues(_ a: inout Int, _ b: inout Int) {
    a += 1
    b += 1
}

var num = 5
changeValues(&num, &num)  //不可以一个变量同时传递给2个输入输出参数   错误:Cannot pass the same variable as inout argument multiple times

上面的代码会导致编译错误,因为不能将同一个变量传递给多个 In-Out 参数,防止变量在函数内部同时被多个地方修改,从而造成数据冲突。

什么是字面量? 

字面量是指在代码中直接写出的值,比如数字、字符串、布尔值等。它们在程序中是固定的、不可以更改的。例如:

  • 5 是一个整数字面量。
  • "hello" 是一个字符串字面量。
  • true 是一个布尔字面量。

警告,inout 参数的修改才会对外部变量生效 ,因此 不要用常量,字面量传递给输入输出参数

 

posted on 2024-10-15 11:43  ACM_Someone like you  阅读(44)  评论(0编辑  收藏  举报

导航