1

我无法弄清楚如何为类/结构中定义的计算变量获取正确的内存地址。我以以下方式定义了一个类(结构也类似):

class TestClass {
    private var a = "Hello"
    
    var getterSetter: String {
        get {
            return a
        }
        set {
            a = newValue
        }
    }
}

为了简单起见,假设我将 ViewController 定义如下:

class ViewController: UIViewController {
    private let testClass = TestClass()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        demoMethod()
        
        print("--------")
        print(testClass.getterSetter)    //Prints "I'm here"
        
        /// Address of testClass
        print("Address of testClass: \(Unmanaged.passUnretained(self.testClass).toOpaque())")
        
        /// Address of computed variable in testClass
        withUnsafePointer(to: &self.testClass.getterSetter) {
            print("Address of computed variable: \(String(format: "%p", $0.pointee))")
        }
        print("--------")
        
    }
    
    private func demoMethod() {
        Observable.just(())
            .subscribe(onNext: { [weak self] in
                guard let self = self else { return }
                self.testClass.getterSetter = "I'm here"
                
                print("*****")
                /// Address of testClass
                print("Address of testClass: \(Unmanaged.passUnretained(self.testClass).toOpaque())")
                
                /// Address of computed variable in testClass
                withUnsafePointer(to: &self.testClass.getterSetter) {
                    print("Address of computed variable: \(String(format: "%p", $0.pointee))")
                }
                print("*****")
            })
            .disposed(by: DisposeBag())
    }
}

getterSetter变量的值在demoMethod函数中被访问和设置,使用一个简单的Observable,这反过来将a更改为"I'm here"。我在 demoMethod 函数内以及在此函数返回之后打印 testClass 和 getterSetter 变量的地址。

请查看此处显示输出的链接。

在这里输出

正如我们从图像中看到的那样,testClass 实例地址保持不变,正如预期的那样。但是,getterSetter 变量的地址在每次打印时显示不同,这没有意义,因为私有变量 a更改为“我在这里”(可以在输出链接中看到),这意味着它们应该指向相同的记忆。

如果我从 demoMethod 中删除self.testClass.getterSetter = "I'm here",它将开始提供正确且相同的内存地址,如下所示:

更新的输出

  • 我相信它必须与Copy on Write机制有关,但我无法弄清楚到底是什么。如果在我执行self.testClass.getterSetter = "I'm here"时将原始实例复制到新内存,那么原始内存地址值怎么会改变?
  • 那么,这里到底发生了什么,内存是如何分配的?

PS此外,当我使用struct TestClass代替类 TestClass时,观察到完全相同的事情,唯一的区别是,我使用print("Address of testClass: (String(format: "%p", unsafeBitCast(self.testClass,到:String.self)))“)

4

0 回答 0