96

私が理解しているように、allocnew、またはcopyで作成されたものはすべて手動でリリースする必要があります。例えば:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

私の質問ですが、これは同じように有効ではないでしょうか?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}
4

7 に答える 7

69

はい、2番目のコードスニピットは完全に有効です。

-autoreleaseがオブジェクトに送信されるたびに、それは最も内側の自動解放プールに追加されます。プールが空になると、プール内のすべてのオブジェクトに-releaseを送信するだけです。

自動リリースプールは、「後で」送信を延期できる便利な機能です。その「後で」はいくつかの場所で発生する可能性がありますが、Cocoa GUIアプリで最も一般的なのは、現在の実行ループサイクルの終わりです。

于 2008-09-15T18:36:18.457 に答える
37

NSAutoreleasePool: ドレインとリリース

drainとの機能がrelease混乱を引き起こしているように見えるので、ここで明確にする価値があるかもしれません (これはドキュメントでカバーされていますが...)。

厳密に言えば、全体像の観点からは、次のものと同等でdrainはありませんrelease

参照カウント環境でdrainは、 は と同じ操作を実行するreleaseため、その意味では 2 つは同等です。強調すると、これは、ではなくを使用すると、プールをリークしないことを意味します。drainrelease

ガベージ コレクション環境でreleaseは、ノーオペレーションです。したがって、効果はありません。 drain一方、「必要に応じて収集する」必要があるというコレクターへのヒ​​ントが含まれています。したがって、ガベージ コレクション環境では、 を使用drainすると、システムがコレクション スイープのバランスをとるのに役立ちます。

于 2008-10-08T01:14:52.060 に答える
17

すでに指摘したように、2 番目のコード スニペットは正しいです。

すべての環境 (参照カウント、GC、ARC) で機能し、ドレイン/リリースの混乱を回避する、自動解放プールのより簡潔な使用方法を提案したいと思います。

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

上記の例では、 @autoreleasepoolブロッ​​クに注意してください。これはここに文書化されています。

于 2011-11-03T07:02:21.997 に答える
7

いいえ、違います。ドキュメントには、非 GC では -drain が -release と同等であることが明確に記載されています。つまり、NSAutoreleasePool はリークされません。

于 2008-09-15T23:55:44.463 に答える
0

release の代わりに autorelease をオブジェクトに送信すると、少なくともプール自体が空になるまで、そのオブジェクトの有効期間が延長されます (オブジェクトが後で保持される場合は、より長くなる可能性があります)。オブジェクトは同じプールに数回入れることができます。その場合、オブジェクトはプールに入れられるたびに解放メッセージを受け取ります。

于 2014-06-27T13:07:08.080 に答える
-2

はいといいえ。ガベージコレクション(メモリ管理されていない)環境でこれを実行した場合、文字列メモリを解放することになりますが、リリースの代わりにドレインを使用してNSAutoreleasePoolオブジェクトをメモリに「リーク」します。この「リーク」により、NSAutoreleasePoolのインスタンスは、GCの下に強力なポインターがない他のオブジェクトと同様に「到達不能」になり、次にGCが実行されるときにオブジェクトがクリーンアップされます。これは、次の呼び出しの直後に発生する可能性があります-drain

ドレイン

ガベージコレクション環境で、最後のコレクション以降に割り当てられたメモリが現在のしきい値より大きい場合、ガベージコレクションをトリガーします。それ以外の場合はリリースとして動作します。...ガベージコレクション環境では、このメソッドは最終的にを呼び出しますobjc_collect_if_needed

-releaseそれ以外の点では、GC以外での動作と似ています。他の人が述べているように、-releaseGCでの操作はありません。したがって、GCでプールが適切に機能することを確認する唯一の方法は、を介することです-drain。非GCで-drainの動作は、非GCでの動作とまったく同じ-releaseであり、間違いなく、良い。

「new、alloc、またはinitで呼び出されたもの」には、「init」を含めないでください(ただし、「copy」を含める必要があります)。「init」はメモリを割り当てず、オブジェクト(コンストラクター)をセットアップするだけだからです。ファッション)。割り当てられたオブジェクトを受け取り、関数がそのようにinitを呼び出すだけの場合、それを解放しません。

- (void)func:(NSObject*)allocd_but_not_init
{
    [allocd_but_not_init init];
}

これは、すでに開始したメモリよりも多くのメモリを消費しません(initがオブジェクトをインスタンス化しないと仮定しますが、とにかくそれらの責任はありません)。

于 2008-09-15T18:39:48.997 に答える