2012-07-12 16 views
1

從: In which situations do we need to write the __autoreleasing ownership qualifier under ARC?不使用__autoreleasing是致命的嗎?

  • (BOOL)保存:(NSError * __autoreleasing *);

編譯器將不得不創建一個臨時變量,設置爲__autoreleasing。所以:

NSError * e = nil; 
[ database save: &error ]; 

將化身:

NSError __strong * error = nil; 
NSError __autoreleasing * tmpError = error; 
[ database save: &tmpError ]; 
error = tmpError; 

好了,現在轉化代碼似乎工作得很好。最後,我期望它能夠正常工作,儘管「小」(很少)有效。那麼爲什麼還要指定autoreleasing?

更確切地說,我知道當我們將指針傳遞給指針時,我們「應該」使用__autoreleasing但是,如果我們得到的僅僅是一個非常輕微的性能增益,那麼有什麼意義呢?

回答

1

當一個變量通過引用傳遞並分配給一個ARC程序時,你錯過了這段代碼中實際發生的事情。

在非ARC編程,保存功能如下:

- (BOOL)save:(NSError * __autoreleasing *)myError { 
    *myError = [[[NSError error] retain] autorelease] 
} 

在ARC編程,保存功能如下:

- (BOOL)save:(NSError * __autoreleasing *)myError { 
    *myError = [[NSError alloc] init]; 
} 

儘管ARC的代碼是什麼樣子,兩個保存函數都會創建一個已被保留並自動釋放的錯誤對象。

這是因爲在ARC版本中,myError指針的類型決定了錯誤對象的內存管理會發生什麼情況。實際上,只要指針是類型__autoreleasing中,* myError分配線是替換

*myError = [[[NSError error] retain] autorelease] 

在運行時。

因此,如果我們能以某種方式將錯誤類型的指針傳遞給保存函數,它會導致保存函數執行錯誤的操作。

由於編譯器將在您的示例中創建一個臨時變量,因此您的代碼可以以任何方式工作,但從ARC編程的角度來看,第一個版本沒有意義。

+0

+1但直到不清楚。所以你說我的方法無論如何都會起作用?所以如果它無論如何起作用,爲什麼還要用不同的方式來宣稱它呢?無論如何,智能編譯器也會生成高效的代碼。 – 2012-09-21 03:38:56

+0

您的方法可以工作,因爲autoreleased臨時變量將在運行循環結束時[或之前]自動釋放,並且強引用在超出作用域[或大約]時釋放,然後該對象將被釋放。這裏重要的一點是,你正在創建保存函數將使用的*指針,所以你必須給它一個指向正確類型指針的引用。如果save函數返回如下錯誤:myError = [self save];則_it_將在內部創建指針,所以不需要臨時變量。 – Colin 2012-09-21 13:18:48

+0

你確定代碼工作?那麼使用__autoreleasing的優勢只是一個稍微快一點的代碼? – 2012-09-22 14:32:53

相關問題