揭秘iOS底层:alloc、new与对象的创建
2023-12-03 01:27:04
深入揭秘 alloc 和 new:iOS 对象创建的幕后机制
前言
在 iOS 开发中,对象创建是一个至关重要的任务。alloc 和 new 是两个常用的方法,但它们在底层是如何运作的呢?本文将深入探究 alloc 和 new 的幕后机制,揭示它们在创建和管理对象时所扮演的角色。
alloc 与 new:异曲同工,各有千秋
alloc 和 new 都是创建对象的途径,但它们之间存在着一些细微差别。
- alloc 是一个类方法,它返回一个指向新对象的指针。
- new 是一个实例方法,它返回一个指向新对象的引用。
在大多数情况下,alloc 和 new 是等价的,但 new 隐式地调用了 alloc,因此从本质上来说,这两个方法最终都归结为 alloc。
alloc 的底层奥秘
当调用 alloc 时,以下步骤将依次发生:
- 查找类对象: 运行时首先找到与调用 alloc 的类关联的类对象。类对象包含有关类的元数据,包括其大小、方法和属性。
- 分配内存: 根据类对象中的大小信息,运行时分配一块内存。这块内存将成为新对象的居所。
- 初始化对象: 运行时调用对象的构造函数来初始化其成员变量。构造函数负责将对象置于一个已知的状态。
- 返回对象指针: 最后,运行时返回一个指向新对象的指针。这个指针可以用来访问和操作对象。
内存管理:堆上舞者
在 Objective-C 中,对象驻留在堆上。这意味着它们被存储在堆栈帧之外的内存区域中。堆栈用于存储临时数据,而堆则用于存储对象。
alloc 负责分配新对象的内存。当对象不再需要时,必须显式释放其内存。这可以通过调用对象的 dealloc 方法来实现。dealloc 方法负责释放对象占用的内存。
底层实现:运行时库的功劳
alloc 和 new 的底层实现取决于平台。在 iOS 上,alloc 和 new 都由运行时库提供。运行时库是一组管理内存和对象生命周期的 C 函数。
alloc 和 new 的 C 语言签名如下:
void *objc_msgSend(id self, SEL _cmd, ...);
其中:
self
是接收消息的对象。对于类方法,这是类对象;对于实例方法,这是对象本身。_cmd
是消息。对于 alloc,这是@selector(alloc)
;对于 new,这是@selector(new)
。...
是可变数量的参数。对于 alloc 和 new,没有参数。
当调用 alloc 时,运行时库执行以下步骤:
- 根据类对象查找类元数据。
- 分配一块与类大小相同的内存。
- 将对象指针返回给调用方。
示例代码:亲身体验
以下示例代码展示了如何使用 alloc 和 new 来创建 NSString
类的实例:
// 使用 alloc
NSString *string1 = [NSString alloc];
// 使用 new
NSString *string2 = [[NSString alloc] init];
// 输出结果
NSLog(@"string1: %@", string1);
NSLog(@"string2: %@", string2);
输出:
string1: (null)
string2: (null)
请注意,输出结果为 (null),因为我们没有显式初始化字符串的内容。
何时使用 alloc 和 new:微妙差别
通常情况下,使用 alloc 和 new 并没有明显的区别。然而,在某些场景中,使用 alloc 更具优势:
- 当需要对一个类进行子类化时。
- 当需要直接访问底层内存时。
- 当需要创建多个对象的数组时。
结论:掌握对象创建的精髓
通过深入理解 alloc 和 new 的底层机制,我们可以更好地掌握 iOS 中的对象创建过程。这些知识对于优化代码性能和避免内存泄漏至关重要。随着我们对底层原理的了解不断深入,我们能够更有效地开发出健壮、高效的 iOS 应用程序。
常见问题解答
-
alloc 和 new 的主要区别是什么?
- alloc 返回一个指针,而 new 返回一个引用。new 隐式地调用了 alloc。
-
对象是如何在堆上管理的?
- alloc 负责分配内存,dealloc 负责释放内存。
-
运行时库在 alloc 和 new 中扮演什么角色?
- 运行时库提供了一组管理内存和对象生命周期的 C 函数。
-
什么时候应该使用 alloc 而不用 new?
- 当需要对一个类进行子类化,直接访问底层内存或创建多个对象的数组时。
-
了解 alloc 和 new 的底层机制有什么好处?
- 可以优化代码性能,避免内存泄漏,并开发出更健壮、高效的应用程序。