2013-08-26 21 views
4

clang允許以下循環語法:@autorelease池和循環機制(for,同時,做)語法

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

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

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

我還沒有發現對語法的任何文件,到目前爲止(蘋果不使用此語法在他們的導遊,至少沒有在導遊介紹@autorelease結構),但它是合理的假設,上述三種說法等同於以下三個語句:

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

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

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

,因爲這是我希望他們(通過標準的C順序稅收規則),但我不完全確定是否真的如此。它也可能是一些「特殊語法」,其中自動釋放池未針對每個循環迭代進行更新。

回答

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: 
+1

通過理論推理它是很好的,在實踐中對它進行測試甚至更好,但是與生成的彙編代碼進行比較的深度恰恰是真正令我信服的答案;-)生成的機器代碼永遠不會存在,因此我會接受你的答案。 – Mecki

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; 
    } 

將通過「迭代10」輸出「Iteration 1」。但是:

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; 
} 
+3

嗯,我知道@autorelease只是下一個語句,但我不確定它是否符合*語句*的條件。由於這是Apple的發明,並且不是任何官方標準的一部分,它可能也只是一個編譯器「提示」(就像一些'__attribute__'語句),而且它們根本不符合* true語句*(不在語言的含義)。 – Mecki

1

我曾嘗試下面的代碼:

@interface Foo : NSObject 
@end 

@implementation Foo 

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

@end 

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

控制檯開始填充已解除分配的Foo實例,因此語法似乎按預期工作。

1

這僅僅是塊和語句正常C語法。當if,else,for,while等沒有大括號時,它們會採用以下語句,這可能是一個複合語句。

例如,你可以這樣做:

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

等等... @autoreleasepool塊並沒有什麼不同。