Swift 什么时候我的结构太大了?

Swift 什么时候我的结构太大了?,swift,class,struct,heap-memory,stack-memory,Swift,Class,Struct,Heap Memory,Stack Memory,鼓励我们在Swift中使用struct而不是class 这是因为 编译器可以做很多优化 实例是在堆栈上创建的,这比malloc/free调用的性能要好得多 struct变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈 例如,想象一个4x4矩阵。必须在每个赋值/返回上复制16个浮点值,在64位系统上为1'024位 避免这种情况的一种方法是在向函数传递变量时使用inout,这基本上是创建指针的快捷方式。但是我们也不鼓励使用inout 所以我的问题是: 我应该如何在Swif

鼓励我们在Swift中使用
struct
而不是
class

这是因为

  • 编译器可以做很多优化
  • 实例是在堆栈上创建的,这比
    malloc
    /
    free
    调用的性能要好得多
  • struct
    变量的缺点是每次从函数返回或分配给函数时都会复制它们。显然,这也可能成为瓶颈

    例如,想象一个4x4矩阵。必须在每个赋值/返回上复制16个浮点值,在64位系统上为1'024位

    避免这种情况的一种方法是在向函数传递变量时使用
    inout
    ,这基本上是创建指针的快捷方式。但是我们也不鼓励使用
    inout

    所以我的问题是:
    我应该如何在Swift中处理大型、不可变的数据结构?
    我需要担心创建一个包含许多成员的大型
    结构吗?
    如果是,我什么时候越过这条线?

    从Swift参考的页面底部开始:

    上面的描述涉及字符串、数组和字典的“复制”。您在代码中看到的行为将始终像复制发生一样。但是,Swift仅在绝对必要的情况下在幕后执行实际复制。Swift管理所有值复制以确保最佳性能,您不应避免分配以尝试抢占此优化

    我希望这能回答您的问题,如果您想确保数组不会被复制,您可以始终将参数声明为
    inout
    ,并将其与
    &array
    一起传递到函数中

    另外,类会增加很多开销,只有在您确实必须对同一对象进行引用时才应该使用

    结构的示例:

    • 时区
    • 经纬度
    • 尺寸/重量
    课程示例:

    • 景色

      • 这个公认的答案并没有完全回答您的问题:Swift总是复制结构。Array/Dictionary/String/etc的诀窍在于它们只是类(包含实际存储的属性)的包装器。这样sizeof(Array)就是指向该类(
        MemoryLayout)的指针的大小

        还有关于容器类型的部分:

        请记住,在使用大值类型之间存在权衡 和使用引用类型。在某些情况下,复制的开销 而围绕大价值类型移动将超过移除的成本 桥接和保持/释放开销


        “我们受到鼓励”谁提出了这个策略?谁想阻止好的代码?@I我的意思是使用结构很有意义。记住,这个建议主要来自Swift团队,他们当然知道,他们自己编写了优化器。可能在某些情况下,这几秒钟是相关的,但我一般认为结构良好的代码有助于提高性能事件错误,这也会导致更好更快的代码。但这只是我的观点。结构促进不变性,这有助于在许多情况下防止错误。区别不是几秒钟,而是可能非常严重。@NSADECT我认为这是你需要测试的事情。当你的应用程序需要更快时,你会知道这是一个瓶颈,打开探查器(仪器)它清楚地说明了瓶颈是复制。不要放弃大型结构的安全性,直到它受到伤害,否则你只会成为过早优化的另一个受害者。这太棒了!事实上,我在Swift出版时读到了这一点,我完全忘了它。你是对的。但引用计数和堆分配的开销不是破坏了使用结构的性能优势?唯一的好处是牛的语义。这取决于你如何看待它。苹果公司的基础知识告诉他们,字符串、数组等都应该是值。事实上,它们不是ObjuleC中的值类型,意味着你经常需要防御地复制它们来保证YO。u对底层存储有一个唯一的引用。COW是一个巨大的性能胜利,因为它用已知需要的副本替换了这些防御副本(例如,因为两个阵列引用指向同一个备份,而一个阵列引用希望变异)。此外,可调整大小的元素将始终需要堆分配。否则,使用数组或字符串的任何堆栈帧的大小将取决于其长度。我记得在第一个Swift测试版中,“let”-带注释的数组仍然是可变的,只要你不改变它们的长度。也许他们是在尝试类似的东西。人们不喜欢这种系统,抗议,我们得到了COW。这是有道理的。尽管我们很少需要防御性地复制数组之类的东西,因为它们在默认情况下是不可变的。我想最大的优点是nt是可变数组和不可变数组的一种类型。还值得注意的是,iOS 11中的Obj-C已经引入了COW,因此这些防御副本的成本应该不会太高。由于编译时泛型、静态调度和积极的内联,Swift可能会更快。结构与类不应该有太大的影响:st指令没有子类型或虚拟成员,但Swift编译器无论如何都可以在同一模块内对非开放类进行设备化。只是更简单的语义。