为什么人们总是对 Objective-C(即 iPhone)中的实例变量使用重新赋值? | 珊瑚贝

Why do people always use reassignment for instance variables in Objective-C (namely iPhone)?


我总是在 viewDidLoad 方法中看到示例代码,而不是说,例如

1
someInstanceVar = [[Classname alloc] init];

他们总是去

1
2
3
Classname *tempVar = [[Classname alloc] init];
someInstanceVar = tempVar;
[tempVar release];

这是为什么?不是完全一样,只是更长吗?

  • 我从未见过这样的构造,您在哪个示例代码中找到了它?能否请您更具体一点。 var 和 tempVar 是成员变量吗?
  • 不仅你永远看不到它。这是不对的。您可能会看到类似的内容,中间线替换为 self.someInstanceVar = tempVar;


简短的回答:这种模式一直出现在 iPhone 代码中,因为它被认为是创建新对象并将其分配给成员变量的最佳方式,同时仍然尊重所有内存管理规则并调用适当的一面效果(如果有的话),同时也避免使用自动释放。

详情:

您的第二个示例将创建一个僵尸,因为 var 保留了一个指向已释放内存的指针。一个更可能的用例如下所示:

1
2
3
tempVar = [[Classname alloc] init];
self.propertyVar = tempVar;
[tempVar release];

假设 propertyVar 是声明为 copy 或 retain 属性,此代码将新对象的所有权移交给类。

更新 1:以下代码是等效的,但在 iOS 上不推荐*,这可能是大多数 iPhone 程序改用第一种模式的原因。

1
self.propertyVar = [[[Classname alloc] init] autorelease];

* 在 iOS 上不鼓励自动释放,因为过度使用它会导致问题。确保您永远不会过度使用它的最简单方法是永远不要全部使用它,因此您会经常看到使用 alloc/init 和 release 的 iOS 代码,即使 autorelease 是可以接受的。这是编码器偏好的问题。

更新 2:由于 Cocoa 在幕后自动执行的内存管理,这种模式起初看起来令人困惑。这一切的关键是用于设置成员变量的点表示法。为了帮助说明,请考虑以下两行代码是相同的:

1
2
self.propertyVar = value;
[self setPropertyVar:value];

当您使用点符号时,Cocoa 将调用指定成员变量的属性访问器。如果该属性已被定义为 copy 或 retain 属性(这是该模式在不创建僵尸的情况下工作的唯一方法),那么会发生几件非常重要的事情:

  • 之前存储在 propertyVar 中的任何值都会被释放
  • 新值被保留或复制
  • 自动处理任何副作用(例如 KVC/KVO 通知)
    • 我的错,修复了代码示例。仍然不明白他们为什么这样做。
    • instanceVar = value 和 this.instanceVar = value 之间有一个关键的区别。使用点符号告诉编译器调用属性访问器,它会在后台自动处理内存管理。
    • 好的,所以点符号调用属性访问器,没有点它只是设置实例变量?…我想念 java…
    • 你通常不使用 self.[a€|] 吗? @marty: self.instanceVar 访问 .h 文件中设置的属性。这也将 retain instanceVar 的新值。
    • @marty:是的,那是正确的 :) 起初这是一个棘手的概念,但如果它咬到你一次,你将永远不会忘记。
    • @e.James @marty 不,这并不完全正确。您需要整个 self. 部分才能实际访问该属性。
    • 哦,因为它使用了属性访问器,所以它被保留了。但我仍然不确定原来的问题。制作临时变量和直接初始化实例变量有什么区别?
    • @marty:我在答案中添加了更多细节,我认为这可能有助于解释。您可以像在第一个示例中那样直接分配给实例变量,但这会让您在以后遇到错误。一个潜在的问题是 instanceVar 中的旧值在分配新值之前没有释放。显然,如果 instanceVar 中没有值,这不是问题,但与其依赖该假设,更容易始终使用”分配、设置属性、释放”模式并轻松睡眠。
    • 您解释了分配给属性的不同之处,但不是为什么在将其分配给属性之前将其分配给临时 var 的原因 – 为什么不简单地 this.propertyVar =[[SomeClass alloc] init]?
    • 好问题。您必须使用中间变量,以便在完成后释放一些东西。如果你调用’self.propertyVar = [[Someclass alloc] init];’,你可以很容易地泄漏新对象。例如,假设”propertyVar”是一个复制属性。然后属性访问器将尽职地复制该新对象,并且该副本将在您的”dealloc”方法中正确释放,但原始对象将被泄露。
    • 我的荣幸。我很高兴你提出了最后一点。我做了这么久,有时我忘记解释一些细节。
    • 你的意思是 self 而不是 this?
    • @Chuck:啊。是的,我当然愿意。感谢您发现这一点。
    • 避免在 iPhone 上使用 autorelease 的建议可能是 Apple 网站上最容易被误解的建议。在这种情况下,例如,自动释放新创建的实例可能会产生最小的影响,因为它可能应该在当前运行循环事件结束后仍然存在。避免自动释放是过早优化的一种情况,因此部分是万恶之源。
    • @JeremyP:这是一个棘手的问题。即使在这个例子中,如果这个代码块只被调用了几次,自动释放也是完全无害的。但是,如果从循环中调用相同的代码块,则影响可能会非常严重。由于很难保证不会从循环中调用特定的代码块,因此最简单的安全方法是完全避免自动释放。
    • @JeremyP:我不会真正称其为优化问题。这更像是 goto 的使用:虽然使用它当然不会导致代码出现问题,但完全不使用它肯定更安全。
    • @e.James:如果,如果,如果…配置文件以找出问题并在您知道存在问题时进行优化。在任何情况下,将循环的每次迭代都package在一个自动释放池中可能比跳过循环以避免自动释放更好。
    • @JeremyP:我同意应该避免过早的优化,但我不认为 alloc/init, assign, release 模式是一种优化。对我来说,这更像是一个方便和安全的问题。如果你总是使用这种模式,你永远不必担心自动释放的潜在副作用。
    • @e.James:并非所有优化都与速度有关。内存占用也有优化。在大多数情况下,alloc/init 和 release 可能比 autorelease 更危险,因为内存泄漏的可能性更大。例如,-stringWithFormat: 为您提供了一个自动释放的对象,您可以在使用后忘记它,但 alloc/initWithFormat: 要求您分配一个临时变量并稍后释放该临时变量。代码更难看,如果你忘记了释放 – 内存泄漏。
    • @JeremyP:我熟悉不同类型的优化,我当然可以看到你对这个问题的看法:避免自动释放以降低临时内存使用量,这是一种内存占用优化。如果您的应用程序是设备上唯一运行的应用程序,并且您可以轻松地分析大多数用例,那么没有理由避免自动释放。
    • 我对此的看法是,由于 iPhone 和其他 iDevices 内存有限,而且您永远不知道您将拥有多少空间,因此最安全的选择是避免自动释放。 Apple 的开发工具很好地发现了您可能通过临时变量引入的任何内存泄漏。


    来源:https://www.codenong.com/3806694/

    微信公众号
    手机浏览(小程序)

    Warning: get_headers(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

    Warning: get_headers(): Failed to enable crypto in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57

    Warning: get_headers(https://static.shanhubei.com/qrcode/qrcode_viewid_10012.jpg): failed to open stream: operation failed in /mydata/web/wwwshanhubei/web/wp-content/themes/shanhuke/single.php on line 57
    0
    分享到:
    没有账号? 忘记密码?