2-2.【OC】【内存管理】alloc / new / copy / mutableCopy 与 retain 在“所有权”上的本质区别是什么?

4 阅读3分钟

虽然这五个操作最终都会导致对象的“引用计数(Reference Count)”增加,但从所有权(Ownership)的哲学和内存物理演进来看,它们有着本质的区别。

我们可以把 alloc/new/copy/mutableCopy 归为一类,把 retain 归为另一类。


1. 核心区别:创建(Creation) vs. 共享(Sharing)

操作本质行为内存变动所有权语义
alloc / new从无到有在堆上分配全新的内存空间,初始化 isa 指针。“我是这块领地的造物主。” 你拥有这块新内存的原始所有权。
copy / mutableCopy克隆产生一份现有对象的副本(通常是新内存,除非是不可变对象的 copy)。“我想要一份一模一样的,但互不干扰。” 你拥有副本的所有权,与原件脱离。
retain认领仅将现有对象的引用计数 +1+1,不分配新内存。“我也要用这个东西,请别在我用完前毁掉它。” 你与他人共享同一个对象的所有权。

2. alloc / new:所有权的起源

这是内存管理的起点。

  • alloc:它是底层 class_createInstance 的封装。它直接向系统申请一块大小为 instanceSize 的内存。
  • new:它等同于 [[Class alloc] init]

本质: 你不仅拥有了所有权,还承担了**初始化(Initialization)**的责任。


3. copy / mutableCopy:所有权的独立

这两个操作体现了 “防御性编程” 的思想。

  • copy:如果你从外部接收一个字符串,你不确定对方是否会突然修改它。通过 copy,你获得了一个属于你自己的、不可变的“快照”。
  • mutableCopy:无论原对象是否可变,都会产生一个全新的、可变的对象。

本质: 这是一种**“断绝关系”**的所有权获取。修改新对象不会影响原对象。


4. retain:所有权的责任分担

retain 是 Objective-C 引用计数模型的灵魂。它不涉及任何内存的重新分配。

  • 底层动作: 现代系统下,它只是修改了 isa 指针里的 extra_rc 位(或者在哈希表 SideTable 里加 1)。
  • 语义: 它代表了一种**“强引用”**。它告诉系统:“只要我不放手(release),这个对象在内存里的物理存在就是合法的。”

5. 一个容易被忽略的细节:copy 的“伪创建”

对于不可变对象(如 NSString),调用 copy 实际上等同于 retain

  • 为什么? 因为既然对象不可变,克隆一份纯属浪费内存。
  • 后果: 此时虽然语义上是“获取副本的所有权”,但物理上你依然是和别人“共享”同一块内存。这是编译器和运行时为了性能做的联合优化。

总结:如何准确判定?

  • 如果你想要一个全新的个体 \rightarrow 使用 alloc/new/copy
  • 如果你只是想延长某个已有对象的生命周期 \rightarrow 使用 retain

判定原则: 在 MRC 中,alloc/new/copy 拿到的对象,其 retainCount 初始就是 1;而 retain 是将现有的计数 +1+1