除了给老派Objective-C程序员心脏病发作外,还有其他任何性能影响:
NSMutableArray *derp = @[].mutableCopy
Run Code Online (Sandbox Code Playgroud)
对此:
NSMutableArray *derp = [[NSMutableArray alloc] init];
Run Code Online (Sandbox Code Playgroud)
dpa*_*age 13
我将给出一个与下面不同的答案.
除非你已经测量了你的应用程序的性能并发现它缺乏,并且发现它在代码的那部分中缺乏正确性,否则你将优化错误的东西.(如果你这样做了,你可以轻松地测量哪一个更快.)
您应该优化代码的清晰度,编写代码的速度以及正确的可能性.
在这方面,我赞成第一个代码片段.它几乎说明了你要做的事情.第一个片段不仅难以阅读; 它还提交使用点表示法来调用方法的样式错误,而不是获取属性的值.
加上导致心脏病发作并不好.:)
类集群没有额外的分配,它与编译器魔法无关.所以是的,你的例子之间存在显着差异(顺便说一句,点符号滥用的互联网点数为-1000.)你的第一个例子有两个分配,第二个只有一个.
由于我们无法访问NSArray的实际源代码,因此我们可以查看GNUStep(一个开源实现)来了解它们如何处理它.在NSArray.m中(简化和省略不相关的东西):
static GSPlaceholderArray *defaultPlaceholderArray;
+ (void) initialize
{
defaultPlaceholderArray = (GSPlaceholderArray*)
NSAllocateObject(GSPlaceholderArrayClass, 0, NSDefaultMallocZone());
}
+ (id) alloc
{
return defaultPlaceholderArray;
}
Run Code Online (Sandbox Code Playgroud)
这里发生的是NSArray定义了一个单独的占位符对象,它始终返回alloc
.当init
在这个单例上调用它时,它会实例化正确的私有子类并返回它.
那么,我们如何判断Apple的基金会是否在做同样的事情呢?很简单,我们只是运行这个测试:
NSArray *a1 = [NSArray alloc];
NSArray *a2 = [NSArray alloc];
NSLog(@"%p, %p", a1, a2);
> "0x100102f30, 0x100102f30"
Run Code Online (Sandbox Code Playgroud)
a1
并且a2
具有相同的内存位置意味着Apple也可能使用单例方法.如果我们打印出类名,__NSPlaceholderArray
那么几乎可以确认它.
所以是的,坚持[NSMutableArray new]
:)
更新:格雷格帕克指出,这@[]
也是一个单身人士,所以@[].mutableCopy
只有一个分配.因此,性能方面的两个例子是相同的.
小智 8
很难确切地知道创建了多少对象,特别是在数组文字的情况下.
官方文档clang
说@[]
扩展到arrayWithObjects:count:
,我怀疑是实现的[[[self alloc] initWithObjects:objects count:count] autorelease]
.
因此,可能会在该点分配第二个对象,因为它NSArray
是一个类集群,并且实现- [NSArray init]
可能看起来像这样:
- (id)init
{
[self release];
self = [[__NSArrayI alloc] init];
return self;
}
Run Code Online (Sandbox Code Playgroud)
为了证实我的怀疑,我写了一个小程序,NSArray
在不同的阶段打印各种类型的对象.注意,为了确实,有必要捕获所有的分配和初始化方法NSArray
.在我们这样做之前,我们只能推测.但无论如何,这是代码:
#import <Foundation/Foundation.h>
int main()
{
NSArray *a = [NSArray alloc];
NSLog(@"NSArray before init: %@", a.class);
a = [a init];
NSLog(@"NSArray after init: %@", a.class);
NSArray *al = @[];
NSLog(@"Array literal: %@", al.class);
NSMutableArray *ma1 = [a mutableCopy];
NSLog(@"NSMutableArray (copied): %@", ma1.class);
NSMutableArray *ma2 = [NSMutableArray alloc];
NSLog(@"NSMutableArray (manufactured) before init: %@", ma2.class);
ma2 = [ma2 init];
NSLog(@"NSMutableArray (manufactured) after init: %@", ma2.class);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是它打印的内容(NSLog()
为清晰起见,删除了杂乱):
h2co3-macbook:~ h2co3$ ./quirk
NSArray before init: __NSPlaceholderArray
NSArray after init: __NSArrayI
Array literal: __NSArrayI
NSMutableArray (copied): __NSArrayM
NSMutableArray (manufactured) before init: __NSPlaceholderArray
NSMutableArray (manufactured) after init: __NSArrayM
Run Code Online (Sandbox Code Playgroud)
编辑:这里有一些涉及挂钩的代码.结果非常有趣但是这会打印很多文本,因此鼓励您编译并运行它.基本上,结果是初始化器没有[NSArray init]
直接通过:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/message.h>
void hook(Class cls, SEL sel, IMP newimp, IMP *old)
{
Method m = class_getInstanceMethod(cls, sel);
*old = method_setImplementation(m, newimp);
}
#define CLS(c) objc_getClass(#c)
#define META(c) objc_getMetaClass(#c)
IMP old_$_NSArray_$_alloc;
IMP old_$_NSMutableArray_$_alloc;
IMP old_$_NSPlaceholderArray_$_alloc;
IMP old_$_NSArrayI_$_alloc;
IMP old_$_NSArrayM_$_alloc;
IMP old_$_NSArray_$_init;
IMP old_$_NSMutableArray_$_init;
IMP old_$_NSPlaceholderArray_$_init;
IMP old_$_NSArrayI_$_init;
IMP old_$_NSArrayM_$_init;
id new_$_NSArray_$_alloc(id self, SEL _cmd)
{
printf("+ [NSArray<%p> alloc]\n", self);
return old_$_NSArray_$_alloc(self, _cmd);
}
id new_$_NSMutableArray_$_alloc(id self, SEL _cmd)
{
printf("+ [NSMutableArray<%p> alloc]\n", self);
return old_$_NSMutableArray_$_alloc(self, _cmd);
}
id new_$_NSPlaceholderArray_$_alloc(id self, SEL _cmd)
{
printf("+ [NSPlaceholderArray<%p> alloc]\n", self);
return old_$_NSPlaceholderArray_$_alloc(self, _cmd);
}
id new_$_NSArrayI_$_alloc(id self, SEL _cmd)
{
printf("+ [NSArrayI<%p> alloc]\n", self);
return old_$_NSArrayI_$_alloc(self, _cmd);
}
id new_$_NSArrayM_$_alloc(id self, SEL _cmd)
{
printf("+ [NSArrayM<%p> alloc]\n", self);
return old_$_NSArrayM_$_alloc(self, _cmd);
}
id new_$_NSArray_$_init(id self, SEL _cmd)
{
printf("- [NSArray<%p> init]\n", self);
return old_$_NSArray_$_init(self, _cmd);
}
id new_$_NSMutableArray_$_init(id self, SEL _cmd)
{
printf("- [NSMutableArray<%p> init]\n", self);
return old_$_NSMutableArray_$_init(self, _cmd);
}
id new_$_NSPlaceholderArray_$_init(id self, SEL _cmd)
{
printf("- [NSPlaceholderArray<%p> init]\n", self);
return old_$_NSPlaceholderArray_$_init(self, _cmd);
}
id new_$_NSArrayI_$_init(id self, SEL _cmd)
{
printf("- [NSArrayI<%p> init]\n", self);
return old_$_NSArrayI_$_init(self, _cmd);
}
id new_$_NSArrayM_$_init(id self, SEL _cmd)
{
printf("- [NSArrayM<%p> init]\n", self);
return old_$_NSArrayM_$_init(self, _cmd);
}
int main()
{
hook(META(NSArray), @selector(alloc), (IMP)new_$_NSArray_$_alloc, &old_$_NSArray_$_alloc);
hook(META(NSMutableArray), @selector(alloc), (IMP)new_$_NSMutableArray_$_alloc, &old_$_NSMutableArray_$_alloc);
hook(META(__NSPlaceholderArray), @selector(alloc), (IMP)new_$_NSPlaceholderArray_$_alloc, &old_$_NSPlaceholderArray_$_alloc);
hook(META(__NSArrayI), @selector(alloc), (IMP)new_$_NSArrayI_$_alloc, &old_$_NSArrayI_$_alloc);
hook(META(__NSArrayM), @selector(alloc), (IMP)new_$_NSArrayM_$_alloc, &old_$_NSArrayM_$_alloc);
hook(CLS(NSArray), @selector(init), (IMP)new_$_NSArray_$_init, &old_$_NSArray_$_init);
hook(CLS(NSMutableArray), @selector(init), (IMP)new_$_NSMutableArray_$_init, &old_$_NSMutableArray_$_init);
hook(CLS(NSPlaceholderArray), @selector(init), (IMP)new_$_NSPlaceholderArray_$_init, &old_$_NSPlaceholderArray_$_init);
hook(CLS(NSArrayI), @selector(init), (IMP)new_$_NSArrayI_$_init, &old_$_NSArrayI_$_init);
hook(CLS(NSArrayM), @selector(init), (IMP)new_$_NSArrayM_$_init, &old_$_NSArrayM_$_init);
NSArray *a = [NSArray alloc];
NSLog(@"NSArray before init: %@<%p>", a.class, a);
a = [a init];
NSLog(@"NSArray after init: %@<%p>", a.class, a);
NSArray *al = @[];
NSLog(@"Array literal: %@<%p>", al.class, al);
NSMutableArray *ma1 = [a mutableCopy];
NSLog(@"NSMutableArray (copied): %@<%p>", ma1.class, ma1);
NSMutableArray *ma2 = [NSMutableArray alloc];
NSLog(@"NSMutableArray (manufactured) before init: %@<%p>", ma2.class, ma2);
ma2 = [ma2 init];
NSLog(@"NSMutableArray (manufactured) after init: %@<%p>", ma2.class, ma2);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2141 次 |
最近记录: |