我在“块编程主题”
中已经阅读过这篇文章“块的每次调用都提供了该变量的新副本。这些变量又可以用作块中包含的块中的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。
任何人都可以帮我理解吗?
答案 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。