【发布时间】: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