3

インスタンス メソッドがコンビニエンス コンストラクターで初期化された値を返す場合、コンビニエンス コンストラクターの自動解放が発生したときにオブジェクトが削除されないように、そのオブジェクトを保持し、戻り値で自動解放する必要がありますか。

これは、呼び出し元のコードの前に説明を解放し、retain などで所有権を取得しますか?

- (NSStringMutable *)test {
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"];
    return description;
}

それともこうあるべき?

- (NSStringMutable *)test {
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"];
    [description retain];                               
    return [description autorelease];
}

コーリング コード:

NSMutableString *testVar = [[NSMutableString alloc] initWithString:[object description]];
4

5 に答える 5

10

いいえ、あなたは大丈夫です:

- (NSStringMutable *)test
{
    return [NSMutableString stringWithString:@"Test Value"];
}

これにより、オブジェクトの保持カウントが 1 のままになり、自動解放プールに入ります。

自動解放プールは特定の時間に排出されます。ガベージ コレクターとは異なります。イベント ハンドラー (ボタン クリック ハンドラーなど) を実装している場合、イベント処理コードから戻ると、自動解放プールはフレームワークによって排出されます。

これを使用した場合:

- (NSStringMutable *)test
{
    NSMutableString *description = [NSMutableString stringWithString:@"Test Value"];
    [description retain];                                                               
    return [description autorelease];
}

...その場合、オブジェクトの保持カウントは 2 になり、自動解放プールに 2 回あり、実際には前のコード例と同じように動作します。

于 2009-08-12T15:02:24.953 に答える
1

あなたはそれを返すことができます。これは、自動リリースの主な目的の 1 つです。独自の自動解放プールを設定していない限り、プールはイベント ループを次に実行するまで排出されません。メモリ管理プログラミング ガイドでは、これらすべてが詳細に説明されています。慣れるまで読んでください。

補足: これ安全ではなく、何らかの奇妙な理由で自動解放プールが早期に排出される場合、2 つの保持と 2 つの自動解放を行っても違いはありません。数はまだバランスが取れているので、ある時点で存在しなくなる可能性があります.

于 2009-08-12T15:03:06.870 に答える
1

私はすでに正しい答えに投票しました。これをスタイルノートとして追加しています:

[object description]呼び出す必要があるときに呼び出しているため、呼び出しコードは機能しません[object test]

本当に文字列を変更できるようにしたい場合を除き、変更可能な文字列を返す必要はありません。状態の変化が最小限であるプログラムを維持する方が簡単だと感じているので、私は自分が書くコードの可変性を最小限に抑えるように個人的に努めています。説明を返すだけなので、変更可能である必要はないと思います。これはサンプルコードにすぎないことはわかっているので、うるさすぎるかもしれません

これを次のように書き換えることができます。

-(NSString *)description {
    // Just return a static NSString. No need to worry about memory management.
    return @"Test Value";
}

そして、呼び出しコードでこの返された文字列の値を変更できるようにしたい場合:

NSMutableString *testVar = [[NSMutableString alloc]initWithString:[object description]];

この文字列に対して alloc を呼び出したので、あなたはそれを所有しており、将来の日付で解放する責任があります。

または、私のお気に入りのコードの 1 つを使用することもできます。

NSMutableString *testVar = [[object description] mutableCopy];

これは、不変オブジェクトの可変コピーを返します (もちろん、NSMutableCopying プロトコルに準拠している場合)。[testVar release]そして、ある段階で送信する必要があります。

そして、これをあなたの質問に対する実際の答えとして結び付けます:オブジェクトにalloccopymutableCopy、またはpreserve を送信すると、オブジェクトを所有し、解放メッセージを送信する責任があります。それ以外は、自動解放されたオブジェクトを返すと想定できます。

繰り返しますが、これはあなたが質問したサンプル コードのほんの一部に過ぎないことはわかっていますが、上記のルールに従えば、メモリ管理の問題のほとんどが解決されます。最初の例では、メッセージ用にこれらのいずれも送信しなかったため、自分でメモリを解放する必要はありません。ただし、alloc呼び出し元のコードに があるため、それを所有testVarしていて解放する必要があります。

于 2009-08-12T15:37:38.927 に答える
0

あなたは2番目のものに近いですが、ここで話しているケースの保持は必要ありません。実際、自分で autorelease を呼び出す必要はありません。

stringWithString はすでに自動解放されたオブジェクトを返すため、これは有効です。

 - (NSStringMutable *)test
 {
   return [NSMutableString stringWithString:@"Test Value"];        
 }

一般に、Objective-C を使用してオブジェクトを作成する場合、(alloc と init を呼び出さずに) 便利なコンストラクターを呼び出している場合、戻り値は常に自動解放されるため、stringWithString は自動解放されたオブジェクトを返します。

于 2009-08-12T15:02:38.790 に答える
0

いいえ、単純に自動解放された値を返すことができます。この理由は、autorelease は変数自体の関数ではなく、(自分で作成しない限り) 通常は実行ループによって管理される autorelease プールの関数であるためです。

于 2009-08-12T14:59:47.640 に答える