0

私はObjective-Cを初めて使用するため、メモリ管理を理解するのに問題があります。(メモリ管理を理解するために)ARCを使用せずにプロジェクトを作成しましたが、メモリリークを回避する方法を知りたいです。

いくつかのC++コードで説明します。たとえば、3つのベクトルで1つの行列を作成したいので、C ++では次のことができます(最初の方法)。

Matrix mat(Vector(1, 1, 1), Vector(2, 2, 2));

関数の最後にすべてのオブジェクトが破棄され、メモリリークは発生しません

Objective-Cでは、次のようなことを行います。

Matrix mat = [[Matrix alloc] init:[[Vector alloc] init:1:1:1]:[[Vector alloc] init:2:2:2]];

C ++では(2番目の方法):

Matrix mat = new Matrix(new Vector(1, 1, 1), new Vector(2, 2, 2));

ただし、この方法では2つのベクトルを破棄できないため、メモリリークが発生します。

だから私の質問は、Objective-Cで最初の方法を実行する方法はありますか?そうでない場合は、2つの一時変数を作成する必要があると思います。これには、2つのベクトルが含まれ、マトリックスの初期化後に解放されます。それとも、それを行う別の方法がありますか?

4

4 に答える 4

2

構文が実際には Obj-C に準拠していないという事実に加えて、そのような場合にメモリを管理するためのいくつかのオプションがあります。

:パラメータを変数に保存したくないと仮定しています。そうでない場合は、コンストラクタに渡した後にそのような変数を解放するだけです。ARC では、リリースする必要がないため、これは大きな違いではありません。

ARCなし。ファクトリ メソッド

Objective-C のファクトリ メソッドは、慣例により自動解放されます。この規則は非常に強力であるため、ARC でさえそのようなメソッドが自動解放されることを期待するため、注意してください。

Matrix *mat = [Matrix matrixWithVectors:[Vector vectorWithCoordinatesX:1 y:1 z:1],
                                        [Vector vectorWithCoordinatesX:1 y:1 z:1],
                                        [Vector vectorWithCoordinatesX:1 y:1 z:1], nil];

の実装はvectorWithCoordinates、例として、次のようになります。

+ (Vector *)vectorWithCoordinatesX:(CGFloat)x y:(CGFloat)y z:(CGFloat)z {
    return [[[Vector alloc] initWithCoordinatesX:x y:y z:z] autorelease];
}

ARCなし。自動解放

パラメータをインラインで作成しているため、パラメータへの参照を保持していない場合は、明示的に自動解放することもできます。

Matrix *mat = [[[Matrix alloc] initWithVectors:[[[Vector alloc] initWithCoordinatesX:1 y:1 z:1] autorelease],
                                               [[[Vector alloc] initWithCoordinatesX:1 y:1 z:1] autorelease],
                                               [[[Vector alloc] initWithCoordinatesX:1 y:1 z:1] autorelease], nil] autorelease];

アーク

ARC では、コンパイラが処理するため、リリースする必要はありません。

だから両方

Matrix *mat = [Matrix matrixWithVectors:[Vector vectorWithCoordinatesX:1 y:1 z:1],
                                        [Vector vectorWithCoordinatesX:1 y:1 z:1],
                                        [Vector vectorWithCoordinatesX:1 y:1 z:1], nil];

Matrix *mat = [[Matrix alloc] initWithVectors:[[Vector alloc] initWithCoordinatesX:1 y:1 z:1],
                                              [[Vector alloc] initWithCoordinatesX:1 y:1 z:1],
                                              [[Vector alloc] initWithCoordinatesX:1 y:1 z:1], nil];

は正しい。

ここでの私の仮定は、Matrixコンストラクターが引数として任意の数のベクトルを取り、nil終了することでもあります。

于 2012-12-30T12:06:51.397 に答える
1

オブジェクトを正しく解放するには、一時変数を使用する必要があるというのは正しいことです。

通常、ARC以前のコードでは、代わりに自動リリースを使用します。

Matrix mat = [[Matrix alloc] init:[[[Vector alloc] init:1:1:1] autorelease] :[[[Vector alloc] init:2:2:2] autorelease]];

または、さらに良いことに、Vectorに便利なメソッドを追加します。

+ (Vector*) vector:(int)a :(int)b :(int)c
{
    return [[[Vector alloc] init:a :b :c] autorelease];
}

次にそれを使用します:

Matrix mat = [[Matrix alloc] init:[Vector vector:1 :1 :1] :[Vector vector:2 :2 :2]];

(ちなみに、コロンの前に単語を付けずにメソッドに名前を付けるのは悪い形式です。読みにくいです。)

于 2012-12-30T11:59:29.197 に答える
0

あなたのObjective-Cコードは間違っています。あなたはあなたの仮定に正しい

だから私の質問は、Objective-Cで最初の方法を実行する方法はありますか?そうでない場合は、2つの一時変数を作成する必要があると思います。これには、2つのベクトルが含まれ、マトリックスの初期化後に解放されます。それとも、それを行う別の方法がありますか?

別の方法は、クラスメソッドを使用して自動解放されたオブジェクトを取得することです。メソッドはプラス記号で始まります。または、自分でベクターを自動リリースすることもできます。

[[[Vector alloc] init:1:1:1] autorelease];

ちなみに、Objective-Cでは名前のないパラメータを使用しないでください。したがって、初期化は次のようになります。

[[[Vector alloc] initWithX:1 y:1 z:1] autorelease];

ただし、ARCを使用して、メモリ管理について心配するのをやめることを強くお勧めします。

于 2012-12-30T11:56:07.930 に答える
0

C ++のように割り当てたすべてのオブジェクトを新規に解放し、削除する必要があります。つまり、1つの方法は、あなたが言うように、一時変数を作成してから解放することです。

ただし、オブジェクトを含む自動解放プールが解放されたときにオブジェクトを解放する自動解放もあります。たとえば、独自のプールを作成していない場合は、メインのNSApplicationループにあります。これにより、この場合、メモリ管理をインラインで実行できます。

それで

Matrix mat = [[[Matrix alloc] init:[[[Vector alloc] init:1:1:1]autorelease]
                  :[[[Vector alloc] init:2:2:2]autorelease]
                  autorelease];

まず、メモリ管理に関するAppleのドキュメントを参照してください。

メカニズムを学ぶためにいくつかの例を見ていきますが、実際の作業を行うにはARCにアクセスします。デバッグするには、基盤となるリリースメカニズムを理解する必要があるかもしれません。

于 2012-12-30T12:00:46.910 に答える