4

我读过垃圾收集是在目标 c 中使用 AUTOZONE(LIBAUTO) 完成的。

垃圾收集器也可用于 OS X 10.8。在学习时,我在想如果垃圾收集器可用,ARC 的需求是什么。然后从 stackoverflow.com 上的来源,我了解了 ARC 和垃圾收集器之间的区别以及两者之间的优势。

现在我知道 ARC 在编译时工作,垃圾收集器在运行时工作。ARC 也不能释放 CFTypes 的内存,它只适用于目标 C 类型。垃圾收集器可以释放使用 ARC 无法完成的保留周期。

现在我想知道我们可以同时使用 ARC 和垃圾收集器,因为两者都在 os x 10.7 中可用。还有为什么垃圾收集器在 10.8 之后被弃用。ARC 是垃圾收集器的替代品吗,它可以释放垃圾收集器完成的所有类型的对象。

此外,由于垃圾收集器在 ios 中不可用,那么在 ARC 之前的 ios 中用于垃圾收集的东西。如果正确完成手动内存管理是否能够管理所有内容,并且如果正确处理手动内存管理就不需要垃圾收集?

4

3 回答 3

4

据我所知,没有(简单的)方法可以同时启用两者,而且无论如何也没有任何意义。

您自己几乎已经回答了这个问题:GC 和 ARC 的用途相同,都是清理内存。GC 具有捕获 ARC 无法捕获的东西的优势,但它有运行时损失。使用 ARC,如果使用不当,您仍然可能会泄漏内存,但如果操作正确(主要是:您遵守命名约定),ARC 的主要优势在于通过出色的运行时性能将您从手动管理负担中解放出来。

所以你选择了一个或另一个,混合它们没有任何意义。如果您启用了 GC,ARC 所做的所有工作将几乎毫无用处,从而浪费性能。

retain顺便说一句,在 ARC 之前,我们使用/进行了手动内存管理release。事实上,这仍然是一种选择,并且仍然被广泛使用(例如,我从事一个大型项目,转换为 ARC 会很麻烦)。

于 2013-11-15T08:54:42.343 回答
2

您不能混合使用 ARC 和 GC,因为 Objective-c 运行时不允许这样做,因为几个概念彼此不兼容:

  • GC 的工作方式是 -retain/release/autorelease/... 不再执行任何操作,为了弥补这一事实,引入了一个新概念,即 -finalize;
  • ARC 的工作方式是你不应该替换 -retain/release/autorelease,编译器会为你发布它们(而不是直接使用 [object retain] 而是只有在你没有替换 -retain/release 时才有效的较低级别的东西/自动释放)。

这些原因确实意味着 GC 和 ARC 的 ABI 非常不同,并且不兼容。

ARC 和 MRR 是兼容的(在某种意义上,您可以混合使用 ARC 构建的代码和使用标准 MRR 构建的代码);GC 和 MRR 是兼容的,因为基本上,如果您在 GC 模式下运行,MRR 调用将被忽略;但 GC 和 ARC 不是。

当我说运行时不允许它时,它意味着在运行时,如果加载框架的应用程序是在 GC 模式下运行的 GC 应用程序,那么任何框架都不能用 ARC 编写,因为那些不支持 GC 并且不能为应用程序加载。

作为副作用,这意味着支持 GC 的 Apple 框架要么使用 CF 或 MRR 编写,它们没有 ARC,可怜的灵魂。

于 2013-12-06T09:01:30.997 回答
2

在 C 中,内存管理通常使用 malloc 和 free 执行。在 C++ 中,new 和 delete 是首选方法。这两者都依赖于开发人员确切地知道他们分配了哪些内存,在哪里(堆栈与堆),并且他们必须只处理一次释放该内存!

如果两个对象引用同一个对象,这会变得很尴尬;哪个负责清理该对象?

Objective-C 决定使用保留/释放来解决这个问题,它管理对象的内部引用计数。当该计数为零时,该对象被删除并释放其内存。此方法通常由开发人员使用 C 和 C++ 手动实现,或使用智能指针自动实现。

纵观 Objective-C 的发展,Apple 一直致力于通过自动化样板代码来使语言更易于使用且不易受常见错误的影响。

因此,手动处理保留和释放的下一步是 GC,但如前所述,在运行时存在 GC 运行时间的开销。GC 二进制文件与手动和自动 (ARC) 的引用计数完全不同且不兼容。这就是为什么在开发系统偏好包时,仍然必须启用 GC,因为主机应用程序(系统偏好设置)继续使用 GC,即使在 Mavericks 中也是如此。忘记使用 GC 编译 3rd 方首选项包将导致包的加载失败。

ARC 的开发回到了保留/释放模型,但是编译器为开发人员处理了这个,使代码更容易编写,更容易阅读。Apple 很可能会沿着这条道路继续前进,而且我每年都希望 Objective-C 变得更加完善。

这就是能够定义编译器和它工作的语言的优势。

在我看来,这样做的不利之处在于,随着语言的发展,新接触该语言的开发人员更难找到不引用旧功能的文档,尤其是在网络上搜索示例代码时。对于刚接触 Objective-C 的开发人员来说,试图破译导致的编译器错误可能是一个巨大的挫败感。

于 2013-11-15T11:16:00.573 回答