swift 中的变异结构函数是否会创建一个新的 self 副本? [英] Does a mutating struct function in swift create a new copy of self?

查看:54
本文介绍了swift 中的变异结构函数是否会创建一个新的 self 副本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢 swift 中的值语义,但我担心变异函数的性能.假设我们有以下 struct

I like value semantics in swift but I am worried about the performance of mutating functions. Suppose we have the following struct

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

现在假设我们创建了一个 Point 并像这样改变它:

Now suppose we create a Point and mutate it as so:

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

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

Now does the existing struct in memory get mutated, or is self replaced with a new instance as in

self = Point(x:self.x+1)

推荐答案

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

Now does the existing struct in memory get mutated, or is self replaced with a new instance

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

Conceptually, these two options are exactly the same. I'll use this example struct, which uses UInt8 instead of Double (because its bits are easier to visualize).

struct Point {
    var x: UInt8
    var y: UInt8

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

假设我创建了这个结构的一个新实例:

and suppose I create a new instance of this struct:

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

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

This statically allocates some memory on the stack. It'll look something like this:

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

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

Let's see what will happen in both situations when we call p.add(x: 3):

  1. 现有的结构体就地变化:

  1. The existing struct is mutated in-place:

我们在内存中的结构看起来像这样:

Our struct in memory will look like this:

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

  • Self 被一个新实例替换:

  • Self is replaced with a new instance:

    我们在内存中的结构看起来像这样:

    Our struct in memory will look like this:

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

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

    Notice that there's no difference between the two scenarios. That's because assigning a new value to self causes in-place mutation. p is always the same two bytes of memory on the stack. Assigning self a new value to p will only replace the contents of those 2 bytes, but it'll still be the same two bytes.

    现在这两种情况之间可能存在一个区别,那就是处理初始化程序的任何可能的副作用.假设这是我们的结构:

    Now there can be one difference between the two scenarios, and that deals with any possible side effects of the initializer. Suppose this is our struct, instead:

    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) 时,你会看到没有进一步打印.这告诉我们初始化器不是新的.

    When you run var p = Point(x: 1, y: 2), you'll see that Init was run! is printed (as expected). But when you run p.add(x: 3), you'll see that nothing further is printed. This tells us that the initializer is not anew.

    这篇关于swift 中的变异结构函数是否会创建一个新的 self 副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆