【问题标题】:Swift: Storing protocol instancesSwift:存储协议实例
【发布时间】:2021-07-06 18:11:26
【问题描述】:

如果实现类型是 ValueType,如何传递协议实例?当您传递协议时,您不知道底层类型。它可以是 ValueType,也可以是 ReferenceType。

我有一个struct MyStruct,它实现了一些协议VectorProtocol。然后我有一个名为 arrayMaker 的函数,它基本上只是要创建 MyStruct 的实例并返回其中一个。这个函数对于这个例子来说有点复杂,我承认。

ArrayMaker 正在返回一个协议,但实现类是一个 ValueType。鉴于这实际上是一个 ValueType,现在如何管理该对象的生命周期?我什至可以将这个协议实例作为其他类的成员存储很长时间。

基本上:我不确定我从这个函数返回的实例是如何在没有引用语义的情况下继续存在的。

结构体是否有可能被 Swift 悄悄提升为引用语义?

import Foundation

protocol VectorProtocol {
    var x: Int { get set }
    var y: Int { get set }
    var z: Int { get set }
}

struct MyStruct : VectorProtocol {
    var x: Int;
    var y: Int;
    var z: Int;
}

func arrayMaker() -> VectorProtocol {
    // protocolArray, and everything in it should be released
    // from memory upon function exit I would think
    var protocolArray: [MyStruct] = []
    for _ in 1...5 {
        protocolArray.append(MyStruct(x: Int.random(in: 0..<10), y: Int.random(in: 0..<10), z: Int.random(in: 0..<10)))
    }
    // only makes sense to me for this to live if semantics are reference
    return protocolArray[3]
}

let vectorProtocol = arrayMaker()

print("Protocol has X Value: \(vectorProtocol.x)")

【问题讨论】:

  • 我不完全确定你在问什么。如果变量具有值类型语义,例如MyStruct,则在分配给另一个变量时,会分配一个副本。如果变量是引用类型 (MyClass),则分配一个引用。无论如何,数组的行为类似于值类型(具有写时复制优化)
  • 你可能会觉得这很有趣:stackoverflow.com/a/68024022/3141234
  • “我认为在函数退出时应该从内存中释放其中的所有内容”。没有。数组本身是一个堆栈分配的(有点复杂)结构,它被返回(通过复制)。数组的存储是堆分配的缓冲区,在函数返回时不会释放。
  • 我知道该数组正在管理一个堆分配的缓冲区,但该数组是在函数的本地范围内声明的,之后没有复制或引用以使其保持活动状态。因此,退出时必须将其全部清理干净。鉴于 Rob 的回答,我选择的条目将被复制到一个框中并返回该结果。数组及其所有内容将被释放。
  • 该链接非常有用,谢谢!

标签: swift


【解决方案1】:

VectorProtocol 的返回值是一个存在的协议,它基本上是一个围绕一个值的 3 个单词“框”。你的值只有 3 个字长,所以它可以装在盒子里。 (如果大于 3 个字,会被复制到堆存储中,由 box 进行内存管理)。

这些 3 字框在堆栈上传递,因此它们不需要任何堆内存。这三个值只是直接放在堆栈上(连同其他几句家务)。

如果这是一个类,那么存在框将只保存一个指向它的指针(以及一些其他的家务)。

这一切都在 WWDC 2016 会议 416“了解 Swift 性能”中进行了解释,但 Apple 似乎已将其从 developer.apple.com 中删除。你仍然可以在WWDC Notes 找到一些关于它的注释,并且可以通过Wayback Machine 获得成绩单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多