2009-06-17 14 views
2

私はObjective-Cの学習に取り組んでいます。私はメモリ管理のための感触を得ようとしています。私はCのメモリ管理にかなり精通していますが、私はObjCの違いを理解しようとしています。 目的匿名オブジェクトのCメモリ管理

のは、私が selfに複素数に渡された追加方法 -(Complex*)add:(Complex*)c;を有し、複素数を保持するために使用される Complexというクラスがあるとしましょう( Complexが変更可能なオブジェクトである、のは言わせて)。

だから私はこのようにそれを呼び出すことができます。

Complex *c = [[Complex alloc] withReal: -3.0 andImag: -2.4]; // c = -3.0-2.4i 
[c add : [[Complex alloc] withReal: 1.0 andImag: 2.0]]; // now c = -2.0-0.4i 

何がaddへの呼び出しで作成した一時オブジェクトのために使用されるメモリはどうなりますか?私はそれがメモリリークだと仮定します。これは正しいコードですか?

Complex *c = [[Complex alloc] withReal: -3.0 andImag: -2.4]; // c = -3.0-2.4i 
Complex *b = [[Complex alloc] withReal: 1.0 andImag: 2.0]; // b = 1+2i 
[c add : b]; // now c = -2.0-0.4i 
[b release]; 

ボーナスnoob質問:Objective-C 2.0 GCはこの状況を処理しますか?最初の例で

答えて

2

最初に、私の「ベストプラクティス」で、カスタムクラスを作成するとき、Objective-Cイディオムは、先頭の「init」を持つイニシャライザ(他の言語の「コンストラクタ」に相当)の名前を付けることです。また、メソッドセレクタの一部、または名前付きパラメータを省略しないでください。これに代えて例えば

、:

- (id) withReal:(double)r andImag:(double)i { ... } 

あなたがこれを行うことを検討する必要があります。2番目の部分は好みの問題である前に

- (id) initWithReal:(double)real imaginary:(double)imaginary { ... } 

ザ・「および」 - 使用することを完全に受け入れますしかし、私はそれが好きではありません。なぜなら、3つ以上のパラメータを持つメソッドにはおそらく使用しないからです。たとえば、使用するRGBカラーを作成する場合、必要以上に冗長になります。-initWithRed:andGreen:andBlue: - 書き込み/使用は通常-initWithRed:green:blue:です。あなたの実際の質問については


、私は完全に便利なクラスのコンストラクタを作成すると、このような状況のために行くためのスマートな方法であることに同意します。これは、あなたが使い捨てのインスタンスを必要とするたびに、alloc-init-autoreleaseよりも視覚的にはるかにクリーンです。上記の変更をマッチング、私はこのように見えるようにケントの答え@微調整します:ボーナスの質問については

+ (Complex*) complexWithReal:(double)real imaginary:(double)imaginary { 
    return [[Complex alloc] initWithReal:real imaginary: imaginary] autorelease]; 
} 

、はい、Objective-Cの2.0のGCはうまくこれを扱うでしょう。最もよく書かれたリリース・リリース・コードはGCの下でそのまま動作します。特に必要がなくなったときにポインタをnilに設定するように注意している場合は特にそうです。 GCが有効な場合、retain/release/autoreleaseへの呼び出しは本質的にno-opsであり、オブジェクトへの参照がなくなるとオブジェクトは収集されます。オブジェクトへの最後のポインタが失われたり、ローカルスコープから外れたりすると、オブジェクトはコレクションの対象となります。 (技術的には、GCはというように、の参照を数えますが、弱い参照を意図的に使用していない限り、この区別は今のところ無関係です)。ガーベジコレクションは現在iPhoneではサポートされていません。

+0

GCのおかげでありがとう - しかし、私はiPhoneで再生を開始する前にしばらく時間がかかる;) – decitrig

+0

確かなこと。 GCを使用することができれば素晴らしいですが、Tigerサポートを落とさなければならないという意味ですが、使用するすべてのフレームワークもGCをサポートする必要があります。しかし、時間が経つにつれて、それはより一般的になり、iPhoneがより速くなるにつれて、おそらくGCをサポートし始めるでしょう。 :-) –

2

[c add : [[Complex alloc] withReal: 1.0 andImag: 2.0]]; 

あなたが参照カウント1を持つオブジェクトが割り当てられているし、あなたがすることはできませんので、あなたがそのオブジェクトへのポインタを格納しないので、それはメモリリークであるので、それが解除されていませんそれにリリースを送ってください。

あなたは「一時的な」オブジェクトを自動解放するためにそれを修正することができます:

[c add : [[[Complex alloc] withReal: 1.0 andImag: 2.0] autorelease]]; 

おそらく、オブジェクトが自動解放されていないという事実を指摘して名前で初期化を使用すると、ユーザーがメモリを処理しなければなりません管理:

initWithReal:(double)r andImag:(double)i 

第2の例は正しいです。

ココアを使用して、リリースに対処する必要はありませんので、あなたは自動解放オブジェクトを返すメソッドを作成することができますたとえば[NSString stringWithString:@"example"]のための自動解放オブジェクトを返します(静的およびメンバーの両方)の多くのメソッドを提供します。

Complex * c = [Complex complexWithReal:1.0 andImag:2.0] 

あなたは可能性があり生データを取るメソッドを作成するaddReal:(double)r andImag:(double)iのようになりますので、alloc/initの手順をスキップできます。

もう1つの選択肢は、Cocoa(CGRectなど)で使用されている構造を使用することです。それらはC言語と同じで、スタックに割り当てられ、alloc/initを使ってヒープ上に割り当てられたオブジェクトとは対照的に、スコープから外れると消えます。頻繁に使用される「小さな」オブジェクトには適していますが、しばしばそれらを保持したくありません。

GCについては、GCがオブジェクトの解放を処理できない理由は何もありません。私はそれをあまり使用しませんでした(いくつかの例を見てみましょう。 python ...)

1

stefanBが正しいです。あなたはこの「オンザフライ」インスタンシエーション(私は仮定します...)の多くをやっているので、静的な「便利な」コンストラクタを構築することは理にかなっています(appKit & coにはたくさんの例があります)。)

メッセージを追加するには、あなたの呼び出しは、このように見えるようになり
+(Complex*) complexWithReal:(double)r andImag:(double)i 
{ 
    return [[Complex alloc] initWithReal:r andImag:i] autorelease]; 
} 

[c add : [Complex complexWithReal:2.0 andImage:1.0]] 

は楽しみを持っています!

関連する問題