4

clang允许以下循环语法:

for (...) @autorelease { ... }

while (...) @autorelease { ... }

do @autorelease { ... } while (...);

到目前为止,我还没有找到关于该语法的任何文档(Apple 在他们的指南中没有使用这种语法,至少在介绍该@autorelease构造的指南中没有使用),但是假设上面的三个语句等同于以下三个声明:

for (...) { @autorelease { ... } }

while (...) { @autorelease { ... } }

do { @autorelease { ... } } while (...);

因为这是我所期望的(按照标准 C 语法规则),但我不完全确定是否真的如此。它也可能是一些“特殊语法”,其中自动释放池不会在每次循环迭代时更新。

4

4 回答 4

8

当您考虑到任何条件语句都可以省略该块时,第一个语法示例起作用的原因就很清楚了{ ... },导致只执行以下语句。

例如:

if (something == YES)
    NSLog(@"Something is yes");

相当于

if (something == YES)
{
    NSLog(@"Something is yes");
}

@autoreleasepool { ... }块只是条件之后的下一条语句。

我个人使用第二种语法,因为它在进行更改时不太容易出错,而且我发现它更容易阅读。想象一下,当您在条件和@autoreleasepool { ... }块之间添加语句时,结果与原始结果有很大不同。看看这个天真的例子......

int i = 1;
while (i <= 10)
    @autoreleasepool
    {
        NSLog(@"Iteration %d", i);
        ++i;
    }

将输出“迭代 1”到“迭代 10”。然而:

int i = 1;
int total = 0;
while (i <= 10)
    total += i;
    @autoreleasepool
    {
        NSLog(@"Iteration %d", i);
        ++i;
    }

实际上会导致无限循环,因为该++i语句永远不会到达,因为它在语法上等同于:

int i = 1;
int total = 0;
while (i <= 10)
{
    total += i;
}

@autoreleasepool
{
    NSLog(@"Iteration %d", i);
    ++i;
}
于 2013-08-26T12:57:31.647 回答
7

两种语法相同

-(void)aFunc
{
    int i=0;
    for(;i<5;)
        @autoreleasepool {
            ++i;
        }
}
-(void)bFunc
{
    int i=0;
    for(;i<5;)
    {
        @autoreleasepool {
            ++i;
        }
    }
}

汇编代码

 "-[AppDelegate aFunc]":                 ## @"\01-[AppDelegate aFunc]"
    .cfi_startproc
Lfunc_begin0:
    .loc    1 12 0                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:12:0
## BB#0:
    pushq   %rbp
Ltmp2:
    .cfi_def_cfa_offset 16
Ltmp3:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp4:
    .cfi_def_cfa_register %rbp
    subq    $32, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    .loc    1 14 12 prologue_end    ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:14:12
Ltmp5:
    movl    $0, -20(%rbp)
LBB0_1:                                 ## =>This Inner Loop Header: Depth=1
    .loc    1 15 5                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:15:5
Ltmp6:
    cmpl    $5, -20(%rbp)
    jge LBB0_3
## BB#2:                                ##   in Loop: Header=BB0_1 Depth=1
    .loc    1 16 26                 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:16:26
Ltmp7:
    callq   _objc_autoreleasePoolPush
    .loc    1 17 13                 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:17:13
    movl    -20(%rbp), %ecx
    addl    $1, %ecx
    movl    %ecx, -20(%rbp)
    .loc    1 18 9                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:18:9
    movq    %rax, %rdi
    callq   _objc_autoreleasePoolPop
    jmp LBB0_1
Ltmp8:
LBB0_3:
    .loc    1 19 1                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:19:1
    addq    $32, %rsp
    popq    %rbp
    ret
Ltmp9:
Lfunc_end0:
    .file   2 "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSObject.h"
    .file   3 "/Users/Parag/Desktop/Test/Test/AppDelegate.h"
    .cfi_endproc

    .align  4, 0x90
"-[AppDelegate bFunc]":                 ## @"\01-[AppDelegate bFunc]"
    .cfi_startproc
Lfunc_begin1:
    .loc    1 20 0                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:20:0
## BB#0:
    pushq   %rbp
Ltmp12:
    .cfi_def_cfa_offset 16
Ltmp13:
    .cfi_offset %rbp, -16
    movq    %rsp, %rbp
Ltmp14:
    .cfi_def_cfa_register %rbp
    subq    $32, %rsp
    movq    %rdi, -8(%rbp)
    movq    %rsi, -16(%rbp)
    .loc    1 22 12 prologue_end    ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:22:12
Ltmp15:
    movl    $0, -20(%rbp)
LBB1_1:                                 ## =>This Inner Loop Header: Depth=1
    .loc    1 23 5                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:23:5
Ltmp16:
    cmpl    $5, -20(%rbp)
    jge LBB1_3
## BB#2:                                ##   in Loop: Header=BB1_1 Depth=1
    .loc    1 25 26                 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:25:26
Ltmp17:
    callq   _objc_autoreleasePoolPush
    .loc    1 26 14                 ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:26:14
    movl    -20(%rbp), %ecx
    addl    $1, %ecx
    movl    %ecx, -20(%rbp)
    .loc    1 27 9                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:27:9
    movq    %rax, %rdi
    callq   _objc_autoreleasePoolPop
Ltmp18:
    .loc    1 28 5                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:28:5
    jmp LBB1_1
Ltmp19:
LBB1_3:
    .loc    1 29 1                  ## /Users/Parag/Desktop/Test/Test/AppDelegate.m:29:1
    addq    $32, %rsp
    popq    %rbp
    ret
Ltmp20:
Lfunc_end1:
于 2013-08-26T13:04:55.507 回答
1

我尝试了以下代码:

@interface Foo : NSObject
@end

@implementation Foo

- (void) dealloc
{
    NSLog(@"Deallocating %@.", self);
    [super dealloc];
}

@end

for (;;) @autoreleasepool {
    [[[Foo alloc] init] autorelease];
    sleep(1);
}

控制台开始填充已释放的Foo实例,因此语法似乎按预期工作。

于 2013-08-26T12:59:34.177 回答
1

这只是块和语句的普通 C 语法。当if, else, for,while等没有大括号时,它们采用以下语句,这可能是复合语句。

例如,您可以这样做:

for (...) if (...) { ... }
if (...) while (...) { ... }

等等......@autoreleasepool块也不例外。

于 2013-08-27T03:34:02.163 回答