博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第六章——函数(inout参数与变异方法)
阅读量:7036 次
发布时间:2019-06-28

本文共 1846 字,大约阅读时间需要 6 分钟。

本文系阅读阅读原章节后总结概括得出。由于需要我进行一定的概括提炼,如有不当之处欢迎读者斧正。如果你对内容有任何疑问,欢迎共同交流讨论。

在Swift中,初次接触inout关键字以及它的用法,可能会让我们想起C/C++中的指针,但实际上Swift中inout只不过是按值传递,然后再写回原变量,而不是按引用传递:

An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.

这样的好处在于它远比使用引用安全。首先举个最简单的例子看一看inout关键字怎么用:

func inc(inout i: Int) {++i}var x = 0inc(&x)print(x)	// 输出结果:“1”复制代码

参数x传入到inc函数中后,在函数内被修改为1,函数返回时这个值(1)覆盖了原来的x的值(0),所以x变成了1。

对比一下另一种同样能在函数内部改变变量值的实现方式——闭包:

func inc() -> () -> Int {var i = 0  //在inc函数内定义变量ireturn { ++i }  // 闭包中截获变量i}let f = inc()print(f()) // 输出结果:“1”print(f()) // 输出结果:“2”复制代码

闭包是通过截获外部变量的引用从而实现对变量的修改的,我们通过闭包来证明,inout参数是按值传递的:

func inc(inout i: Int) -> () -> Int {return { ++i }  // 闭包中截获inout参数i}var x = 0let f = inc(&x)print(f()) // 输出结果:“1”print(x) // 输出结果:“0”复制代码

如果inout参数是按引用传递,因为我们知道闭包会按引用截获变量,所以闭包内的++i语句实际上会影响到我们定义的变量x,因此最后一个输出的结果应该是1,但实际上运行结果是0。

这说明inout参数是按值传递的,我们梳理一下整个过程:

  • 首先变量x的值是0,它作为inout参数传入inc方法中,inc方法内有一个x的副本,闭包截获了这个副本的引用。
  • 随后inc方法方法返回,此时的副本值还是0,所以外部的变量x的值为0。
  • 接下来我们调用闭包,副本值被改为1,但是外部的变量x的值不会受到任何影响,所以它依然为0。

如果在inc方法中返回闭包之前就调用这个闭包,那么外部的变量x的值就会被修改为1,这是因为在函数返回前,副本的值变成了1:

func inc(inout i: Int) -> () -> Int {let f = { ++i }  // 闭包中截获inout参数if()return f}var x = 0let f = inc(&x)print(x) // 输出结果:“1”复制代码

&并不总表示inout

如果在函数声明中,参数是一个UnsafeMutablePointer的指针,那么传递参数的时候也要加上&,这和inout参数看上去用法类似,但实际上这里是按引用传递而不是按值传递。我们可以改写一下之前的inc方法:

func inc(i: UnsafeMutablePointer
) -> () -> Int {//函数内存储指针i的副本,闭包截获这个副本return {i.memory++return i.memory}}复制代码

这个方法的使用与之前类似。有兴趣的读者可以自行尝试。这里我们换一种调用方式,传入inc方法的参数不是整数地址,而是数组的地址:

let f: () -> Intdo {var x = [0]f = inc(&x)}print(f())复制代码

为了与C兼容,Swift中的数组可以自动转成指针,但由于数组的地址不确定,所以这种写法其实会产生一种未定义行为(UB)。

需要注意的是,使用&时,也许我们用的是Swift的inout语义,这是安全的,也许用的是UnsafeMutablePointer的指针,这需要我们格外小心。我们需要考虑它所指向的对象的生命周期。在后面的章节中会更加详细的讨论这一点。

转载地址:http://feyal.baihongyu.com/

你可能感兴趣的文章
jvm调优
查看>>
sqlserver数据库附加分离备份还原命令
查看>>
【边框】-边框阴影-box-shadow
查看>>
POJ2001 Shortest Prefixes(字典树)
查看>>
hihocoder1181 欧拉路
查看>>
运算符
查看>>
windows开机启动nginx
查看>>
Scoket 服务器监听多个客户端发来的图片
查看>>
time,datetime,时间戳 时间格式转换
查看>>
7种html5css3网页图片展示特效代码
查看>>
对象的序列化和反序列化
查看>>
Joiner
查看>>
CSS3技巧:fit-content水平居中
查看>>
0506-Scrum 项目 2.0视频
查看>>
[Android Pro] AAR and JAR
查看>>
hdu 2276 Kiki & Little Kiki 2
查看>>
巧克力棒&&新年的巧克力棒
查看>>
[CQOI2014]危桥
查看>>
接口自动化之接口整理(抓包)
查看>>
矩阵运算(二维数组)
查看>>