快速的变异结构函数是否会创建新的self副本?

loo

我喜欢迅速地使用值语义,但是我担心变异函数的性能。假设我们有以下内容struct

struct Point {
   var x = 0.0
   mutating func add(_ t:Double){
      x += t
   }
}

现在,假设我们创建了一个Point并对其进行了变异:

var p = Point()
p.add(1)

现在struct,内存中的现有变量是否发生了突变,或者被self替换为新的实例,如

self = Point(x:self.x+1)
亚历山大-恢复莫妮卡

现在,内存中的现有结构是否发生了突变,或者被新实例自行替换了?

从概念上讲,这两个选项是完全相同的。我将使用此示例结构,该结构使用UInt8而不是Double(因为它的位更易于可视化)。

struct Point {
    var x: UInt8
    var y: UInt8

    mutating func add(x: UInt8){
       self.x += x
    }
}

并假设我为此结构创建了一个新实例:

var p = Point(x: 1, y: 2)

这会在堆栈上静态分配一些内存。它看起来像这样:

00000000  00000001  00000010  00000000
<------^  ^------^  ^------^ ^----->
other    | self.x | self.y | other memory
          ^----------------^
          the p struct

让我们看看在两种情况下调用时会发生什么p.add(x: 3)

  1. 现有的struct就地进行了突变:

    我们在内存中的结构将如下所示:

    00000000  00000100  00000010  00000000
    <------^  ^------^  ^------^ ^----->
    other    | self.x | self.y | other memory
            ^----------------^
            the p struct
    
  2. 将Self替换为新实例:

    我们在内存中的结构将如下所示:

    00000000  00000100  00000010  00000000
    <------^  ^------^  ^------^ ^----->
    other    | self.x | self.y | other memory
            ^----------------^
            the p struct
    

注意,这两种情况之间没有区别。那是因为给self赋一个新值会导致就地突变。p在堆栈上始终是相同的两个字节的内存。为self分配新值p只会替换这2个字节的内容,但仍将是相同的两个字节。

现在,两种情况之间可能存在一个差异,该差异处理了初始化程序的任何可能的副作用。假设这是我们的结构,而不是:

struct Point {
    var x: UInt8
    var y: UInt8

    init(x: UInt8, y: UInt8) {
        self.x = x
        self.y = y
        print("Init was run!")
    }

    mutating func add(x: UInt8){
       self.x += x
    }
}

运行时var p = Point(x: 1, y: 2),您会看到Init was run!已打印出来(按预期)。但是,当您运行时p.add(x: 3),您会看到没有进一步打印。这告诉我们初始化器不是新的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章