arrayWithCapacity
是 NSArray.h 中定义的方法,并在 NSArray.m
当我查看GNUStep提供的代码时,我可以得到arrayWithCapacity
是一种调用initWithCapacity
的常规方法:
+ (id) arrayWithCapacity: (NSUInteger)numItems
{
return AUTORELEASE([[self allocWithZone: NSDefaultMallocZone()]
initWithCapacity: numItems]);
}
initWithCapacity
是一种只进行自我初始化的简单方法。
- (id) initWithCapacity: (NSUInteger)numItems
{
self = [self init];
return self;
}
没有关于执行项目数量的内存分配
使用arrayWithCapacity
方法有什么好处?简单地使用[[NSArray alloc] init]
?
答案 0 :(得分:8)
期望提供显式大小可以改善内存分配,因为在添加项目时无需调整数组的大小。在实践中,它只是一个提示,并且有一些证据证明它实际上并未使用(请参阅基础集合类中的objc.io article)。
答案 1 :(得分:2)
这些方法实际上是NSMutableArray
的一部分,而不是NSArray
。
它为实现提供了一个关于你想要存储多少项的提示,因此它可以预先分配足够的内存而不是根据需要增加内存,这可能很昂贵,因为它可能涉及分配,从旧的复制内存到新的,释放旧记忆。如果你添加了很多项目,这种增长可能会发生很多,所以如果NSMutableArray
可以一次性分配所需的内存量,效率会更高。
请记住,这只是一个提示,实现可能会忽略它。实际上,CFArray/CFMutableArray
在创建可变数组时忽略容量:
static CFArrayRef __CFArrayInit(CFAllocatorRef allocator, UInt32 flags, CFIndex capacity, const CFArrayCallBacks *callBacks) {
struct __CFArray *memory;
UInt32 size;
...
switch (__CFBitfieldGetValue(flags, 1, 0)) {
case __kCFArrayImmutable:
size += capacity * sizeof(struct __CFArrayBucket);
break;
case __kCFArrayDeque:
case __kCFArrayStorage:
break;
}
...
return (CFArrayRef)memory;
}
CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks) {
...
return (CFMutableArrayRef)__CFArrayInit(allocator, __kCFArrayDeque, capacity, callBacks);
}
根据@azsromej链接的this article,NSMutableArray
似乎也忽略了提示。
答案 2 :(得分:1)
这适用于NSMutableArray
,因为NSArray
没有方法arrayWithCapacity
,这也适用于initWithCapacity
:
从运行时POV中使用arrayWithCapacity
可以忽略不计。它可以被认为是一种过早的优化。
它确实有缺点,或者需要一些时间和/或代码来提出一个很少提供有意义的时间优势并增加心理负担的值。
它也被认为是暗示,可能会或者不会被使用,这是Apple可以在任何时候改变的实现细节。
注意:我使用和不使用容量提示进行了时序测试,节省的时间(如果有的话)是一个非常小的百分比。
有关NSArray
的详细信息,请参阅ridiculousfish。
@bbum评论:"文档只是状态建立初始容量,而不是数组已分配内存来容纳所有容量。 Array的后备存储不是线性分配的内存块,细节随阵列的大小而变化。"