以一個方法起頭:html
- (void)createCat {
NSObject *cat = nil;
if (!cat) {
cat = [[NSObject alloc] init];
//1
}
//2
}
複製代碼
當調用 createObject 方法, object 對象會在何時釋放? 我猜大部分人會回答在位置2釋放. 從語法層面解釋也比較容易, 局部變量在做用域內默認是 strong 的, 因此出了做用域局部變量纔會釋放.bash
而如果咱們在位置2增長 log, 也很容易證明這一點, 的確在位置2的時候沒有釋放.app
然而實際狀況並無這麼簡單, 從現象看來用薛定諤的貓比喻比較恰當: 當你在觀察它, 它就是活的, 當你不觀察他, 它已經死了.優化
固然咱們的觀察是"直接"打印它. 但何時代碼變成玄學了? 看到這裏你確定認爲博主在胡謅, 下面作個試驗: 咱們建立一個 weak 修飾的 property, 當建立一個 cat 後, 讓這個 property 指向這個 cat. 咱們經過 log 這個 weak property 間接"觀察"它有沒有死.spa
//_catWeakProperty 爲 weak property
- (void)createCat {
NSObject *cat = nil;
if (!_catWeakProperty) {
cat = [[NSObject alloc] init];
_catWeakProperty = cat;
}
NSLog(@"cat: %@", _catWeakProperty);
//NSLog(@"cat: %@", cat);
}
複製代碼
運行起來, 沒錯, 打印出來的 cat 真的是 nil, 已經釋放, 但你將下一行註釋打開, 直接 log 這個對象, 它又並無釋放.code
看到這裏是否是以爲很沒有道理, 實際上是仍是有道理的, 上面沒有說清楚運行環境: 這些代碼只有在 ARC ==Release== 環境中才會是這種效果, 若是在 Debug 環境中, 不管如何這個對象不管如何都不會釋放. 若是在網上搜 Debug 和 Release 的相關不一樣, 會發現不少博客都有說 Debug 環境內存會延遲釋放, 而 Release 環境內存達到釋放時機會當即釋放. 這樣說也沒毛病, 實際按蘋果官方的說法這只是 ARC 環境中運行時的一些優化, 但具體優化策略蘋果是不會告訴你的...htm
Is ARC slow?對象
It depends on what you’re measuring, but generally 「no.」 The compiler efficiently eliminates many extraneous retain/release calls and much effort has been invested in speeding up the Objective-C runtime in general. In particular, the common 「return a retain/autoreleased object」 pattern is much faster and does not actually put the object into the autorelease pool, when the caller of the method is ARC code.內存
-- Transitioning to ARC Release Notesci
這種狀況很是特殊, 必須是 weak property(__weak 不會優化), 局部變量的生成在其餘的做用域, ARC/Release 環境纔會有這樣的優化, 這也算是蘋果的又一個坑吧, 記錄一下, 之後查問題能夠留個心眼.