1

次の 2 つのシナリオについて教えてください。これらはほとんど似ていますが、小さいオブジェクトと大きいオブジェクトが含まれています。

シナリオ 1:

次のコードでは:

NSString *iAmAstring;
for(int i = 0; i < 100000;i++)
{
     NSLog(@"INT VALUE: %d", i);
     iAmAstring = [NSString stringWithFormat:@"%d", i];
     NSLog(@"STRING VALUE: %@", iAmAstring);
}

ARCをオンにして以来、上記の大規模なループを実行しても意味がなく、ループ実行ごとに文字列ポインターを割り当てて初期化していると言われました。小さすぎて問題にならないと言われたので、ARCはそれを処理できます. しかし、より大きなオブジェクトでそれを行うべきではありません。私はもともとC#のバックグラウンドから来ており、ループの最後で文字列をnullに設定することに慣れていますが、ここではループの最後で文字列を解放できないため、ARCが文句を言い、設定するとnilループの最後で、ARC の作業をさらに作成することになりますが、実際には正しいことを行っておらず、ゾンビ コードを作成しています。ループの最後にARCをオンにして、メモリサイズが小さい大規模なループ(できれば私が使用した文字列)で初期化して、割り当てているオブジェクトに何をするかを明確にすることはできますか?

シナリオ 2:

上記と同じですが、上記で使用されている NSSTRING がサイズの大きい別のオブジェクトになったとします。ここでは明らかにループの前に割り当てて初期化し、それを設定してループで使用しますが、ループの最後で再び何かをして少し解放するので、もう一度ARCをオンにしますか?

前もって感謝します。

4

2 に答える 2

4

ARCでは、自動解放プールを@autoreleasepool {}ブロックで定義します。これらのブロックは、自動解放されたオブジェクトの新しいプールを作成し、ブロックのスコープが終了したときにそれらを排出します。

NSString *iAmAstring;
for(int i = 0; i < 100000;i++)
{
    @autoreleasepool {
         NSLog(@"INT VALUE: %d", i);
        iAmAstring = [NSString stringWithFormat:@"%d", i];
        NSLog(@"STRING VALUE: %@", iAmAstring);
    }
}

これにより、自動解放プールが排出され、ループの各反復ですべての自動解放オブジェクトが解放されます。これは小さな文字列では無駄なことですが、大きなオブジェクトでは非常に役立つ場合があります。

自動解放がどのように機能するかについての簡単なメモ:それが行うのはrelease、プールが空になったときにオブジェクトにもう1つの呼び出しを与えることだけです。デフォルトのプールは、イベントループで排出されます(つまり、メソッドが終了した後しばらくすると)。手動で作成したプールは、スコープが@autoreleasepool終了すると排出されます。

私は元々C#のバックグラウンドを持っていて、ループの最後の文字列もnullに設定することに慣れています。

後で変数を再利用しない限り、これによりプログラムに完全に役に立たないコード行が追加されます。C#コンパイラは、オブジェクトをガベージコレクションで使用できるようにするための最も早いポイントを理解するのに十分なほど賢いので、割り当て役に立たnullない。

于 2012-07-25T04:59:13.727 に答える
0

私が理解できないのは、オブジェクトを作成するためにalloc / initを使用し、オブジェクトを破棄するために明示的なリリースを使用するのではなく、自動リリースプールを使用する必要があると人々が考える理由です。

自動解放プールを必要とする副作用があるオブジェクトがいくつかありますが(日付、私はあなたを見ています)、ほとんどの場合、

{
    NSString *s = [[NSString alloc] initWithFormat:...];
    ....
    [s release];
}

ループ内では、自動リリースに依存するよりも効率的です。

シナリオ2に関しては、申し訳ありませんが、NSStringは不変です。値を変更しないでください。

于 2012-07-25T07:38:58.790 に答える