質問

clang allows the following loop syntax:

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

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

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

I haven't found any documentation on that syntax so far (Apple doesn't use this syntax in their guides, at least no in the guides introducing the @autorelease construct), but is it reasonable to assume that the three statement above are equivalent to the three statements below:

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

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

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

Since that is what I would expect them to be (going by standard C syntax rules), yet I'm not entirely sure if that's really the case. It could also be some "special syntax", where the autorelease pool is not renewed for every loop iteration.

役に立ちましたか?

解決 2

Both syntax are same

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

Assembly code

 "-[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:

他のヒント

The reason that the first syntax example works is clear when you consider that any conditional statement can omit the { ... } block, resulting in only the following statement being executed.

For example:

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

is equivalent to

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

The @autoreleasepool { ... } block is simply the next statement following the conditional.

Personally I use the second syntax as it's less error-prone when making changes, and I find it easier to read. Imagine that when you add a statement between the conditional and the @autoreleasepool { ... } block, the result is considerably different from the original. See this naive example...

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

Will output "Iteration 1" through "Iteration 10". However:

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

Will actually cause an infinite loop because the ++i statement is never reached as it is syntactically equivalent to:

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

@autoreleasepool
{
    NSLog(@"Iteration %d", i);
    ++i;
}

I have tried the following code:

@interface Foo : NSObject
@end

@implementation Foo

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

@end

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

The console starts to fill with the deallocated Foo instances, so the syntax appears to work as expected.

This is just the normal C syntax for blocks and statements. When if, else, for, while, etc. do not have braces, they take the following statement, which could be a compound statement.

For example, you can do:

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

and so on... @autoreleasepool blocks are no different.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top