0

最近、Autorelease Pool Blocks に出くわしたとき、 Advanced Memory Managementのドキュメントを読んでいました。ドキュメントには次のように記載されています。

ループ内で自動解放プール ブロックを使用して、次の反復の前にこれらのオブジェクトを破棄できます。ループ内で自動解放プール ブロックを使用すると、アプリケーションの最大メモリ フットプリントを削減できます。[...] 自動解放プール ブロック内で自動解放メッセージを送信されたオブジェクトは、ブロックの最後で解放されます。

autorelease 呼び出しを取得しないブロック内で作成されたオブジェクトはどうですか? それらの保持カウントも 0 にデクリメントされると仮定します。次に、私の質問は、どちらにしても、ブロック内で作成されたオブジェクトがブロックの最後でリリース呼び出しを取得するときに、autorelease を呼び出すポイントは何ですか?

4

1 に答える 1

2

オブジェクトは、-releaseまたは-autoreleaseメッセージを送信することで解放できます。

参照カウントを使用-releaseすると、すぐにデクリメントされ、割り当て解除につながる可能性があります。

デクリメントを使用-autoreleaseすると、オブジェクトが作成されたスコープを超えてオブジェクトを存続させることが延期されます。たとえば、ヘルパー メソッド-createFooは自動解放されたオブジェクトを返す場合があります。これにより、呼び出し元は、返されたオブジェクトを、メソッドから戻ったときにすぐに割り当てを解除せずに使用でき、解放の責任者を気にする必要もありません。

ARC を使用すると、コンパイラがこれらすべての詳細を処理します。知っておく必要があるのは、 を使用すると、オブジェクトが少し長く存続する場合があるということだけautoreleaseです。

この「キープ アライブ」動作は、次のようなループに影響します。

- (void)foobar
{
    for (/* a long time */) {
        NSMutableString *s = [NSMutableString string];
        // ...
    }
}

+stringメソッド onは、自動解放されたNSMutableStringオブジェクトを返します。これは、ループの繰り返しまたはメソッドの最後で自動的に割り当て解除されるわけではありません(まあ、ARC はコール スタックを調べることで巧妙な最適化を行うことができますが、これは無視します)。これは、ループ本体の内部にいる間、メモリが無限に増加することを意味します。

以下を使用した場合に注意してください。

NSMutableString *s = [[NSMutableString alloc] init];

次に、ARC はreleaseループ本体の最後に呼び出しを挿入し、文字列はすぐに解放されます。

最初の例の無制限のメモリ増加を回避するには、明示的な自動解放プールを定義します。

- (void)foobar
{
    for (/* a long time */) {
        @autoreleasepool {
            NSMutableString *s = [NSMutableString string];
            // ...
        }
    }
}

これで、ループの各反復の後、自動解放プールが破棄され、プール内で自動解放されたすべてのオブジェクト (文字列を含む) がすぐに解放されます。

したがって、呼び出しているメソッドの種類と、それらが自動解放されたオブジェクトを返すかどうかによって異なります。

于 2013-04-23T07:32:37.977 に答える