我有纯ARC编码的经验。作为一个编译器特性,它尊重objective - c方法族,在需要的时候可以正确地保留/释放调用。
所有以alloc
, mutableCopy
, copy
和new
开头的方法创建一个新对象。他们增加了留存数。因此,当我不再需要指针时,ARC将释放任何指针(以及与之关联的对象)。
我认为当我编写不遵循命名约定的方法时可能会出现问题。例如,如果我写一个像newCustomer
这样的方法,在第一个版本中返回一个自动释放的对象,而在第二个版本中没有,会发生什么?
特别是,我的问题如下(它们属于相同的推理):
- 如果调用和被调用的代码都是用ARC编译的,会发生什么?
- (a)如果调用代码用ARC编译而被调用代码用非ARC编译会发生什么?
- (b)如果调用代码用非ARC编译而被调用代码用ARC编译会发生什么?
如果你的回答能说明ARC是如何工作的(objc_release
, objc_retainAutoreleasedReturnValue
等),我将不胜感激。
提前感谢。
名为newCustomer
的方法属于new
方法族,因此被隐式标记为返回保留对象。当调用者和被调用者的代码都用ARC编译时,那么ARC会在调用者中释放一个release来平衡额外的保留:
来源当从这样的函数或方法返回时,ARC保留该值在返回语句的求值点,在离开所有当地的范围。
当从这样的函数或方法接收返回结果时,ARC释放包含它的完整表达式末尾的值
如果newCustomer
是用手动引用计数实现的,并且违反了命名约定(即,不返回保留的对象),则调用者可以过度释放或释放不足,这取决于具体情况。
如果调用者使用ARC,那么从newCustomer
返回的对象将被过度释放——很可能导致程序崩溃。这是因为调用代码将参与上述过程的后半部分,而在此之前没有执行相应的保留。
如果调用代码不是用ARC编译的,但被调用的代码是(因此正确地实现了返回一个保留的对象),那么行为取决于程序员遵循命名约定。如果它们释放返回值,那么对象的引用计数将被正确管理。但是,如果程序员认为他们的new...
方法确实违反了命名约定,并且没有在调用代码中手动插入release,那么返回的对象将会泄漏。
总而言之,正如Martin R.在评论中指出的那样,关键的决定因素是在包括手动引用计数在内的任何环境中是否遵循命名约定。
就像任何其他语言一样,当您违反该语言的一些基本假设时,您就会陷入未定义行为的领域。在未来的某个时候,苹果可能会修改-new...
如何进行引用计数的内部结构。苹果公司有责任确保符合预期用途的代码能够正常工作,但他们不会为不符合预期用途的代码这样做。
如果您需要知道运行在特定系统上的特定版本的编译器的实际行为是什么,那么您必须对其进行测试。不要认为其他编译器或运行时版本的行为是相同的。
最后,未定义行为就是未定义行为。当您构建依赖于它的代码时,您最终将受到微妙且难以诊断的缺陷的影响。