56

オブジェクトを割り当てて初期化する次の 2 つの方法の違いは何ですか?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

self.aController= [[AController alloc] init];

リンゴの例のほとんどは、最初の方法を使用しています。なぜ割り当て、初期化、オブジェクト化を行った後、すぐに解放するのでしょうか?

4

6 に答える 6

71

すべてのオブジェクトには参照カウントがあります。0 になると、オブジェクトの割り当てが解除されます。

プロパティが次のように宣言されていると仮定します@property (retain)

あなたの最初の例、行ごと:

  1. オブジェクトは によって作成されalloc、参照カウントは 1 です。
  2. selfオブジェクトはのsetAController:メソッドに渡されretain、メソッドはメッセージを送信し (メソッドはオブジェクトの送信元を認識していないため)、参照カウントを 2 に増やします。
  3. 呼び出しコードはオブジェクト自体を必要としなくなったため、 を呼び出しrelease、参照カウントを 1 に減らします。

2 番目の例では、基本的にステップ 1 と 2 を実行しますが、3 は実行しないため、最後にオブジェクトの参照カウントは 2 になります。

ルールは、オブジェクトを作成した場合、それを使い終わったらそれを解放する責任があるということです。あなたの例では、プロパティを設定した後、コードは tempAController で実行されます。retainそのオブジェクトを固定する必要がある場合に呼び出すのは、setter メソッドの責任です。

self.property = foo;Objective-C では、実際には の省略形で[self setProperty:foo];あり、setProperty:メソッドは必要に応じてオブジェクトを保持またはコピーすることを覚えておくことが重要です。

プロパティが宣言@property (copy)されている場合、オブジェクトは保持される代わりにコピーされます。最初の例では、元のオブジェクトはすぐに解放されます。2 番目の例では、元のオブジェクトの参照カウントは 0 であるべきなのに 1 になってしまいます。そのため、同じ方法でコードを書きたいと思うでしょう。

プロパティが宣言されている場合は@property (assign)selfオブジェクトの所有権を主張しておらず、他の誰かがそれを保持する必要があります。この場合、最初の例は正しくありません。これらの種類のプロパティはまれであり、通常はオブジェクト デリゲートにのみ使用されます。

于 2008-10-01T04:54:29.090 に答える
31

他の人が指摘したように、表示する 2 つのコード スニペットは同等ではありません (メモリ管理上の理由から)。後者よりも前者が選ばれる理由については、次のとおりです。

後者の正しい定式化は次のようになります。

self.aController= [[[AController alloc] init] autorelease];

前者と比較すると、自動解放プールの使用により追加のオーバーヘッドが追加され、状況によっては (自動解放プールが解放されるまで) オブジェクトの有効期間が不必要に延長され、アプリケーションのメモリ フットプリントが増加します。

他の「可能な」実装 (例がどこからのものかによる) は単純です:

aController = [[AController alloc] init];

ただし、インスタンス変数を直接設定することは、init メソッドまたは dealloc メソッド以外では絶対にお勧めできません。それ以外の場合は、常にアクセサー メソッドを使用する必要があります。

これにより、サンプル コードに示されている実装が表示されます。

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

これは、次の理由からベスト プラクティスに従います。

  • 自動解放を回避します。
  • これにより、メモリ管理のセマンティクスがすぐに明確になります。
  • アクセサー メソッドを使用してインスタンス変数を設定します。
于 2008-10-03T16:37:03.277 に答える
5

また、多くの人が Autorelease を使用する理由は、コードを 1 行にまとめたいというあなたの願望であることにも注意してください。

self.aController = [[[AController alloc] init] autorelease];

理論的には、iPhone の autorelease はどういうわけかコストがかかるため (明確な説明を聞いたことがありません)、オブジェクトを別の場所に割り当てた直後に明示的に解放することをお勧めします。

于 2008-10-01T07:03:56.550 に答える
5

Xcode を使用している場合は、静的アナライザーでそのようなコードを検出するのに役立ちます。ビルド>>ビルドと分析を押すだけです

代替テキスト

これにより、そのようなコードで非常に役立つメッセージが表示されます。

代替テキスト

于 2011-01-14T18:07:04.467 に答える
4

もう1つ注意すべき点は、例がaControllerの@property定義にも依存していることです。

として定義されている@property (readwrite, retain) id aController;場合、例は機能しますが、として定義されている場合@property (readwrite, assign) id aController;、releaseへの追加の呼び出しにより、オブジェクトの割り当てが解除されます。

于 2008-10-01T18:38:04.743 に答える
2

あなたもすることができます

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

保持プロパティを使用すると、同じように機能しますが、混乱が少ないため、他の方法(プロパティを保持するため)を使用することをお勧めします。そのコードは、aControllerを割り当てたように見え、実際にはメモリから削除されます。 setAControllerがそれを保持しているからではありません。

于 2009-08-04T00:24:53.543 に答える