欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Swift学习(四):函数

程序员文章站 2022-04-11 17:50:04
...

函数的定义

func: 声明这是一个函数

sum:函数名

(v1:  Int,  v2: Int): v1,v2是参数名, Int是参数类型

-> Int:返回值为Int

sum(v1:  10, v2:  20):调用函数,调用函数时有参数名(v1, v2)必须带着

Swift学习(四):函数

形参默认是let,也只能是let

  • 无返回值的函数

Swift学习(四):函数

->()表示返回值为空,()实际上是一个空元组

Swift学习(四):函数

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

隐式返回

如果整个函数体是一个单一表达式,那么函数会隐式返回这个表达式

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

返回元组:实现多返回值

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

函数的文档注释

Swift学习(四):函数       Swift学习(四):函数

参考:https://swift.org/documentation/api-design-guidelines/

-------------------------------------------------------------------------------------------------------------------------------

参数标签(Argument Label)

  • 可以修改参数标签

Swift学习(四):函数

  • 可以使用下划线加空格_ 省略参数标签

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

默认参数值(Deafault Parater Value)

  • 参数可以有默认值

Swift学习(四):函数

  • C++的默认参数有个限制:必须从右往左设置。由于Swift拥有参数标签,所以并没有此类限制
  • 但是在省略参数标签时需要特别注意:要传入的没有默认值的参数必须要设置参数标签

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

可变参数(Variadic Parameter)

Int...:表示一个或多个类型为Int的参数

Swift学习(四):函数

一个参数最多只能有一个可变参数

紧跟在可变参数后面的参数不能省略参数标签,否则会认为是可变参数中的其中一个参数

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

Swift自带的print函数

Swift学习(四):函数

Swift学习(四):函数 

-------------------------------------------------------------------------------------------------------------------------------

输入输出参数(In-Out Parameters)

注意:Swift屏蔽掉了一些东西,不能直接输出地址,会报错

Xcode进入汇编模式: DeBug --> Debug  Workflow --> Always Show Disassembly

下图:callq(表示这是一个函数方法) 0x100000f60表示函数地址

Swift学习(四):函数

lea:汇编里的地址传递指令, 表示把0x10da加rip表示的地址传递给rdi,用%开头的表示寄存器,也就是说rdi里存的是地址值

(%rdi)表示根据rdi存储的地址值找到相应的存储空间

mov指令是赋值指令。

 Swift学习(四):函数

普通参数传递和inout参数地址传递汇编代码对比:

/*
这是普通参数传递,明显有mov赋值指令
 var number = 10
 
 func test(_ num: Int) {
 
 }
 
 test(number)
 
 0x100000f5e <+78>: movq   -0x30(%rbp), %rdi
 0x100000f62 <+82>: callq  0x100000f70               ; TestSwift.test(Swift.Int) -> () at main.swift:24
 
这是inout输入输出参数,没有mov赋值指令,有lea地址指令
 var number = 10
 
 func test(_ num: inout Int) {
 
 }
 
 test(&number)
 
 0x100000f47 <+55>: leaq   0x10ca(%rip), %rdi        ; TestSwift.number : Swift.Int
 0x100000f4e <+62>: callq  0x100000f70               ; TestSwift.test(inout Swift.Int) -> () at main.swift:24
 */

 这里说汇编是因为要论证函数的输入输出参数(inout)是地址传递,并不是网上其他人说的先把参数传给一个中间值,然后把中间值当作返回值返回,然后赋值给外部参数,这里涉及到汇编就不多说了。

  • 可以用inout定义一个输入输出参数:可以在函数内部修改外部实参的值,比如交换两个数的值

Swift学习(四):函数

也可以用元组Swift学习(四):函数

  • 可变参数不能标记为inout
  • inout参数不能有默认值
  • inout参数的本质是地址传递(引用传递) 
  • inout参数只能传入可以被多次赋值的(也就是需要用var,不能用let,更不能用40这种字面量)

-------------------------------------------------------------------------------------------------------------------------------

函数重载

  • 规则:
  1. 函数名相同
  2. 参数个数不同 || 参数类型不同 || 参数标签不同

Swift学习(四):函数

和第一个相比参数个数不同

Swift学习(四):函数

和第一个相比参数类型不同

Swift学习(四):函数

和第一个相比参数标签不同

Swift学习(四):函数

相应的输出结果:

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

函数重载注意点

  • 返回值类型与函数重载无关,即使不一样也会报错

Swift学习(四):函数 编译器分不清该用哪个

  • 默认参数值和函数重载一起使用产生二义性,但是编译器不会报错(在C++中会报错)

Swift学习(四):函数 默认使用第一个sum函数

  • 可变参数、省略参数标签、函数重载一起使用产生二义性时,编译器有可能会报错

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

内联函数(Inline Function)

  • 如果开启了编译器优化(Release模式默认会开启优化,Debug模式默认不开启,需要手动调整),编译器会自动将某些函数变为内联函数。
  • 将函数调用展开成函数体(比如将function test {print("A")} 直接转化成print("A"),消除了函数体的调用,节省了内存开销)

Swift学习(四):函数

  • 哪些函数不会被内联
  1. 函数体比较长
  2. 包含递归调用
  3. 包含动态派发

-------------------------------------------------------------------------------------------------------------------------------

函数类型(Function Type)

  • 每个函数都是有类型的,函数类型由形式参数类型、返回值类型组成

Swift学习(四):函数 函数类型为: () -> Void 或 () -> ()

Swift学习(四):函数  函数类型为: (Int, Int) -> Int

Swift学习(四):函数  通过函数类型定义变量,调用时不需要参数标签

  • 函数类型作为函数参数

Swift学习(四):函数

  • 函数类型作为函数返回值

Swift学习(四):函数 其中forward(_ forward: Bool) -> (Int) ->Int 表示forward(_ forward: Bool)这个函数的返回值是一个函数类型,即(Int) ->Int,它表示一个参数为Int,返回值也是Int类型的函数

返回值是函数类型的函数,叫做高阶函数。

-------------------------------------------------------------------------------------------------------------------------------

typealias

  • typealias用来给类型起别名

Swift学习(四):函数

typealias给元组起别名

Swift学习(四):函数

typealias给函数类型起别名IntFn,将IntFn作为参数类型和返回值类型

Swift学习(四):函数

-------------------------------------------------------------------------------------------------------------------------------

嵌套函数(Nested Function)

  • 将函数定义在函数内部

Swift学习(四):函数