是否在执行时复制了块?

时间:2012-07-19 01:17:21

标签: objective-c

我在“块编程主题”

中已经阅读过这篇文章

“块的每次调用都提供了该变量的新副本。这些变量又可以用作块中包含的块中的const或by-reference变量。”

所以,我测试了以下代码。

// Employee.h
@interface Employee : NSObject
@end

// Employee.m
@implement Employee
@end

// main.m
int main() {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    Employee* john = [[Employee alloc] init] autorelease];

    void (^blockTest)(void) = ^ {
        NSLog(@"john = %@", john);
        NSLog(@"john retain count = %ld", [john retainCount]);
    };

    blockTest();

    [pool drain];
    return 0;
}

我预计执行blockTest时“John”保留计数将为2,但结果为1。

任何人都可以帮我理解吗?

3 个答案:

答案 0 :(得分:1)

您的报价不完整。如果您阅读了之前的内容:

  

在块的词法范围内声明的局部变量,其行为与函数中的局部变量完全相同。

您会看到更准确的引用是:

  

每次调用块都会提供[局部变量]的新副本。这些变量又可以在块中包含的块中用作const或by-reference变量。

john不是本地的,因此报价不适用;它适用于块中定义的变量。此外,"提供了一个新副本"并不意味着copy消息被发送到变量内容,这意味着有一个单独的变量具有相同的名称,就像每个函数调用产生一个局部变量的新副本一样("行为与函数中的局部变量完全相同")。

typedef int (^IntFunc)(int);
typedef IntFunc (^IntFuncFunc)(int);

int main() {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    IntFuncFunc makeAdder;
    IntFunc add2, add3;

    makeAdder = ^(int x) {
        // 'x' is local to this block. Each invocation provides a new copy of 'x'
        return (IntFunc) [[^(int y) {
            return x + y;
        } copy] autorelease];
    };
    add2 = makeAdder(2);
    add3 = makeAdder(3);
    // add2 and add3 each refer to an 'x', but it's not a shared 'x'        
    NSLog(@"add2(0): %d\nadd3(0): %d\n", add2(0), add3(0));

    [pool drain];
    return 0;
}

输出:

add2(0): 2
add3(0): 3

答案 1 :(得分:0)

关于retainCount来自Apple

  

重要说明此方法在调试内存中通常没有任何价值   管理问题。因为任何数量的框架对象都可能有   保留一个对象,以便保持对它的引用,而在   同时自动释放池可能持有任何数量的延迟   在一个对象上发布,你不太可能获得有用的东西   这种方法的信息。

答案 2 :(得分:0)

注意:假设为此答案禁用ARC,就像在ARC环境中一样,这会完全改变。

当一个块捕获一个变量时,它会将指针const复制到你正在使用的对象,而不是对象本身。

示例:

void copyPointer(NSObject *input)
{
    NSLog(@"I have copied the input's pointer! %@", input);
}

void copyObject(NSObject *input)
{
    input = [input copy];

    NSLog(@"I have copied the object itself! %@", input);

    [input release];
}

因此,当你调用-retainCount时,它等同于外部变量的retainCount,因为没有调用的方法可以增加接收者的retainCount。