8

私の理解では、これらは両方とも NSMutableString を作成します。最初のものだけがシステムによって所有され、2 番目のものは私によって所有されます (つまり、解放する必要があります)。どちらか一方を使用する必要がある特定の理由はありますか? また、コンパイラにサイズ感を与えるため、最初の方が優れていますか?

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

また

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

編集...また

宣言が 2 行で書かれているのをよく見かけます (つまり)。

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

個人的にはワンライナーの方が好きですが、これは単なる個人的なスタイルの例ですか?

4

6 に答える 6

16
NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

また

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

どちらか一方を使用する必要がある特定の理由はありますか?

はい。特別な理由がない限り、常にすぐに自動解放してください。

release最初の理由は、メッセージを書くのを非常に忘れやすいからです。オブジェクトを作成したのとまったく同じステートメントで ( のように) オブジェクトを自動解放すると[[[… alloc] init] autorelease]、それを忘れるのがはるかに難しくなり、忘れたときに明らかになります。便利なファクトリ メソッド ( などstringWithCapacity:) がオブジェクトを自動解放するので、自分で自動解放する場合と同様に、後で解放することを心配する必要はありません。

第二に、別のメッセージを書くことを覚えていても、releaseヒットしないのは簡単です. 早期返品には 2 つの方法があります。

NSString *str = [[NSString alloc] initWithString:@"foo"];

BOOL success = [str writeToFile:path atomically:NO];
if (!success)
    return;

[str release];

およびスローまたは伝播された例外:

NSString *str = [[NSString alloc] initWithString:@"foo"];

//Throws NSRangeException if str is not in the array or is only in the array as the last object
NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1];

[str release];

「そうしない具体的な理由」は、通常、多くのオブジェクトを作成するタイトなループがあるためです。この場合、オブジェクト数を維持するために、ループ内のできるだけ多くのオブジェクトを手動で管理することをお勧めします。下。ただし、これが問題であるという証拠がある場合にのみ、これを行ってください(Shark からのハード ナンバー、Instruments からのハード ナンバー、またはそのループが十分に長く実行されるたびにシステムがページング地獄に陥っている場合)。

他の、おそらくより良い解決策には、ループを 2 つのネストされたループ (内側のループの自動解放プールを作成および排出するための外側のループ) に分割し、NSOperation に切り替えることが含まれます。(ただし、キューが一度に実行する操作の数に制限を必ず設定してください。そうしないと、ページング地獄に陥りやすくなる可能性があります。)

また、コンパイラにサイズ感を与えるため、最初の方が優れていますか?

その方が良いですが、その理由ではありません。

コンパイラにとっては、これは単なる別のクラス メッセージです。コンパイラは、自分が何をするかを知りませんし、気にもしません。それが知っていて気にかけているのstringWithCapacity:は、ユーザーに曲を再生するメッセージだけです。

NSMutableStringにサイズのヒントが与えられます。クラスは、最初に割り当てたい文字ストレージの量を認識します。これによって得られるメリットはおそらく小さいものですが (少なくとも Mac では)、情報が手元にある場合は、それを使用してみませんか? 逆に、私はそれを計算するためにわざわざ行くつもりはありません。

宣言が 2 行で書かれているのをよく見かけます (つまり)。

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

個人的にはワンライナーの方が好きですが、これは単なる個人的なスタイルの例ですか?

はい。ただし、変数を初期化しないままにしておくと、ある程度のリスクがあります。これを習慣化する場合は、必ず「Run Static Analyzer」ビルド設定をオンにしてください。

于 2009-09-28T17:15:25.907 に答える
4

前者は必ずしもコンパイラ向けではなく、データの格納を最適化する方法に関する文字列への提案です。これは、データ セットのサイズに応じて実装を内部的に変更できるNSDictionary/NSArray/NSSet に最も役立ちます。

それ以外は、あなたは正しいです。唯一の違いは所有権の問題です。WithCapacity私はメソッドをほとんど使用せず、[NSMutableString string]or[NSMutableArray array]を使用するだけですが、IMO、それは実際にはスタイルの問題であり、一方を他方に使用しても何も得ることも失うこともありません。

于 2009-09-28T15:38:34.623 に答える
2

最初のものは自動解放された文字列です。これは、適切な時点でシステムによってリリースされます。自動解放プールに追加され、メモリはシステムによって処理されます。範囲外になると、それが有効であることを保証することはできません。このタイプは、メソッド内にスコープしかない場合や、メソッドから値を返す場合に役立ちます。

2番目は保持されるため、参照カウントは1になり、自動解放プールには追加されません。あなたはそれを解放し、メモリを解放する責任があります。オブジェクトのスコープを制御する場合は、このメソッドを使用します。メンバー変数などに使用されます。

2行の初期化は単なるスタイルだと思いますが、次の行にいる場合でも、値を割り当てずに変数を定義しているため、2行のバリエーションは使用しません。この種のミラーメンバー変数の宣言/初期化を推測しますが、個人的にはあまり好きではありません。

于 2009-09-28T15:58:42.950 に答える
1

あなたは有効な質問を持ち出します。それは本当にあなたがしていることに依存しますが、一般的なiPhoneアプリの場合、私は最初のものを使用すると言います。これは、参照カウントが0になると自動的にクリーンアップされ、心配する必要はありません。

文字列のメモリを自分で管理する正当な理由がある場合は、2番目のものを使用してください。文字列をいつクリーンアップする必要があるかを確認したい場合や、特定の時間にメモリが最小限になることを期待したい場合などです。

原則として、正当な理由がある場合は2番目のものを使用してください。

于 2009-09-28T15:40:57.943 に答える
1

あなたはすべての点で正しいです!

サイズ/容量のヒントがどれほど大きな違いをもたらすかはわかりませんが、より多くの情報があれば、実行時により適切な決定ができ​​るはずです。

あるスタイルを他のスタイルよりも優先して使用する理由 さて、自動解放されたオブジェクトはいつ解放されるのでしょうか? それが重要である理由は 2 つあります。まず、メソッドがすぐに解放できる大量のメモリを使用する場合。(ローカルの autorelease プールを使用することもできます。) 次に、autorelease を使用すると、メモリ リークが隠され、一部のコードのデバッグがより困難になることがわかりました。走行距離は、コードの年齢と品質によって異なる場合があります。

iPhone アプリの開発を始めた当初は、常に自動解放オブジェクトを使用していました。すべてがどのように機能するかを完全には理解していなかったので便利でしたが、通常は正しいことを行いました. 最近では、手動でメモリの割り当てを解除する側で過ちを犯す傾向があります。参照カウントがどのように機能するかを実際に理解し、理解していないときにすぐに問題を強制する場合は、それほど難しくありません。

于 2009-09-28T16:17:58.193 に答える
0

必要な文字列の長さが十分にわかっている場合は、先に進んで -initWithCapacity: メソッドを使用してください。文字列のストレージを超えると、再割り当てとコピーが行われますが、これは安価な操作ではありません。

于 2009-09-28T17:11:51.703 に答える