Swift中的函数是值类型还是引用类型?又为什么呢?

时间:2018-11-23 16:38:57

标签: swift

考虑此功能:

func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

在这里,我将此功能分配给另一个变量

var mathFunction: (Int, Int) -> Int = addTwoInts

这里addTwoInts是值类型还是引用类型?为什么呢?

3 个答案:

答案 0 :(得分:3)

我想说一个函数类型最适合the definition of a reference type

  

将引用类型分配给变量或常量或将其传递给函数时,不会复制引用类型。

而不是副本,而是使用对相同现有实例的引用。

但是,我认为这并不是一个特别有用的区别,IMO提出将函数定义为值类型(如technically speaking they consist of a pointer and a reference的论点也是有效的,当函数值过去了。

最有用的区别是函数具有引用语义,这意味着可以观察实例之间的某种共享状态。这与引用类型不同–值类型可能具有引用语义,而引用类型可能具有值语义。

例如,这是具有参考语义的值类型:

var foo = 0
struct S {
  var bar: Int {
    get { return foo }
    nonmutating set { foo = newValue }
  }
}

let s = S()
let s1 = s
s.bar += 1
print(s.bar)  // 1
print(s1.bar) // 1

ss1都共享全局状态,这可以通过对其进行突变来观察。

这是具有值语义的引用类型:

final class C {
  let foo = 0
}

let c = C()
let c1 = c
print(c.foo)  // 0
print(c1.foo) // 0

尽管cc1都具有共享状态,但这不是直接可观察到的,因为该共享状态是不可变的。

那么,为什么函数具有引用语义?因为它们可以包含捕获的变量,这是可以观察到的共享可变状态。

例如:

func makeFn() -> () -> Int {
  var foo = 0
  return {
    foo += 1
    return foo
  }
}

let fn = makeFn()
let fn1 = fn
print(fn())  // 1
print(fn1()) // 2

答案 1 :(得分:2)

封闭和功能为参考类型。 Swift语言文档中对此进行了说明:Closures

答案 2 :(得分:2)

闭包和函数是引用类型

Apple 说:每当您将函数或闭包分配给常量或变量时,实际上是将该常量或变量设置为对函数或闭包的引用。

在下面的例子中, incrementByTen 所指的是闭包的选择是常量,而不是闭包的内容。

让我们试试看这个例子:

首先我将创建一个函数,以Integer为参数返回一个名为makeIncrementer的函数

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    
    return incrementer
}

现在 incrementByTen 将引用这个函数的结果。换句话说,引用一个闭包

let incrementByTen = makeIncrementer(forIncrement: 10)

incrementByTen()
// returns a value of 10

到目前为止一切顺利.. 如果我再次调用 incrementByTen() 呢? 结果是 10 还是 20 ? 是的,你明白了:) 它将是 20。因为 闭包和函数是引用类型,正如我在开头所说的那样。

incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30 with same approach as i explained.