Swift中如何让结构体实例共享同一属性且避免拷贝?
问题场景与代码示例
我会实例化大量B类型的值,且A的实例值永远不会改变,B的很多函数都需要依赖这个A实例才能运行。现有两种实现方式,但都存在缺陷:
Case 1: 将A作为结构体属性
struct A {} struct B { let a: A // 大量依赖a的函数 func foo1() -> B {...} func foo2() -> B {...} ... } let a = A() let b = B(a: a) b.foo1()
缺陷:每次创建新B实例都会拷贝a,当A体积较大时会带来不必要的性能开销。
Case 2: 每次调用函数传入A
struct A {} struct B { func foo1(a: A) -> B {...} func foo2(a: A) -> B {...} ... } let a = A() let b = B() b.foo1(a: a)
缺陷:无需拷贝a,但每次调用函数都要手动传入,开发体验差。
我希望能存储a但不拷贝它,就像C语言中使用引用那样,请问有什么解决方案?
解决方案
1. 用类包装A(最常用、推荐)
利用Swift中类的引用语义,要么直接把A改为类,要么用类包装结构体A的实例,这样B存储的是类实例的引用,不会拷贝A的内容:
// 方案1:直接将A改为类 class A {} struct B { let a: A func foo1() -> B {...} func foo2() -> B {...} } let a = A() let b = B(a: a) b.foo1() // 方案2:用类包装结构体A struct A {} class ABox { let value: A init(_ value: A) { self.value = value } } struct B { let aBox: ABox func foo1() -> B { // 通过aBox.value访问A实例 ... } } let a = A() let aBox = ABox(a) let b = B(aBox: aBox)
无论创建多少B实例,都会共享同一个类实例的引用,不会产生A的拷贝。
2. 使用不安全指针(仅性能极度敏感场景)
如果不想修改A的类型,可使用UnsafePointer存储A的内存地址,但需要手动保证A实例的生命周期长于所有B实例,否则会出现野指针问题,日常开发不推荐:
struct A {} struct B { let aPtr: UnsafePointer<A> func foo1() -> B { let a = aPtr.pointee ... } } let a = A() let b = B(aPtr: &a) // 必须确保a的生命周期覆盖所有使用b的代码
3. 自定义引用语义包装结构体(兼顾语法与安全性)
用内部类存储A实例,对外暴露结构体接口,既保留值类型的使用习惯,又实现引用语义的共享:
struct A {} struct SharedA { private final class Storage { let value: A init(_ value: A) { self.value = value } } private let storage: Storage init(_ value: A) { self.storage = Storage(value) } var value: A { storage.value } } struct B { let sharedA: SharedA func foo1() -> B { let a = sharedA.value ... } } let a = A() let sharedA = SharedA(a) let b = B(sharedA: sharedA)
内容的提问来源于stack exchange,提问作者damdamo
相关产品推荐
相关产品推荐

