每次调用count方法时,NSMutableArray是否实际计算项目?

Sup*_*tar 4 performance objective-c nsmutablearray

因为可可设计模式,实例方法的名称countNSMutableArray是不明确的; 它可以要么返回保存的变量count,或者它的每个,它被称为时间可以指望数组中的项,并返回(可可决定了仅返回一个变量的值的方法foofoo,不getFoo).Objective C NSMutableArray实际上是在每次count调用方法时计算项目,还是返回预先计算的变量的值?如果这是Java,我会查看源代码,但我找不到源代码NSMutableArray.我查看了API,它说的只是:

返回当前数组中的对象数.

由于没有上下文,我无法判断这是否意味着它内部进行了任何计算.

Chu*_*uck 7

正如您已经正确指出的那样,无法保证它会以某种方式运行.

但实际上,这-[NSArray count]是一个恒定时间的操作.您可以通过创建一个小数组和一个大型数组并对获取计数所需的时间进行基准测试来自行确认.count像这样在核心数组类上使用O(n)方法会非常愚蠢.


Car*_*zey 5

NSArray声明一个私有的ivar _used,它似乎保存了数组的计数.使用object_getInstanceVariable()您可以验证在具体子类的情况下__NSArrayM,此变量在添加和删除对象时递增和递减.

我使用以下程序(Mac OS X Foundation命令行工具)来验证:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        NSMutableArray *anArray = [NSMutableArray array];
        NSLog(@"anArray's concrete class is %@", [anArray class]);
        UInt64 used = 0;
        for (NSString *toAdd in @[@"o", @"m", @"g"]) {
            object_getInstanceVariable(anArray, "_used", (void **)&used);
            NSLog(@"array = %@, used = %lld", anArray, used);
            [anArray addObject:toAdd];
        }
        for (NSString *toRemove in [anArray copy]) {
            object_getInstanceVariable(anArray, "_used", (void **)&used);
            NSLog(@"array = %@, used = %lld", anArray, used);
            [anArray removeObject:toRemove];
        }
        object_getInstanceVariable(anArray, "_used", (void **)&used);
        NSLog(@"array = %@, used = %lld", anArray, used);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序产生了以下输出:

2013-01-31 17:40:15.376 Array[10173:303] anArray's concrete class is __NSArrayM
2013-01-31 17:40:15.378 Array[10173:303] array = (
), used = 0
2013-01-31 17:40:15.378 Array[10173:303] array = (
    o
), used = 1
2013-01-31 17:40:15.379 Array[10173:303] array = (
    o,
    m
), used = 2
2013-01-31 17:40:15.379 Array[10173:303] array = (
    o,
    m,
    g
), used = 3
2013-01-31 17:40:15.380 Array[10173:303] array = (
    m,
    g
), used = 2
2013-01-31 17:40:15.380 Array[10173:303] array = (
    g
), used = 1
2013-01-31 17:40:15.380 Array[10173:303] array = (
), used = 0
Run Code Online (Sandbox Code Playgroud)