1

参照数の増加について調査しています。それを見つけるのを手伝ってください。以下はサンプルコードであり、以下の各行の参照カウントで何が起こるかを調査しています。

.hファイル

NSArray *tempArray;
@property (nonatomic, retain) NSArray *tempArray;

.mファイル

@synthesize tempArray;

    -(void) sampleFunction
{
    NSArray *myArray = [[NSArray alloc] init]; // Thinking reference count increases to "1"
    tempArray = myArray;// reference count increases and tempArray gets retain count "1" now.
    tempArray = myArray;// reference count increases and tempArray gets retain count "2" now.
    tempArray = [NSArray arrayWithObject:@"SomeString"]; // retain count = ?

}

このコードは機能するためのものではないかもしれませんが、これはそのようなシナリオの参照カウントで何が起こるかを調査するためだけのものです。保持カウントを印刷しようとしましたが、正しい結果が表示されません。この各行で参照カウントがどのように機能するかを教えてください。

4

4 に答える 4

4

実際にはretain count、new、alloc、retain、copy の状態でのみ増加しますが、これを介してオブジェクトに所有権を提供している場合、retain countそれ以外は増加する可能性はありませんretain count

于 2013-07-02T06:58:34.717 に答える
4

2、3、4 行目では、インスタンス変数tempArrayを と同じオブジェクトに影響を与えていますmyArray。しかし、このように書くと、インスタンス変数に影響を与えようとします。実際のところ、コードに@synthesize tempArrayまたは@synthesize tempArray = tempArrayを記述していない場合、デフォルトでは、プロパティ値を格納するために自動的に生成されるインスタンス変数は、プロパティ名と同じ名前になりますが、先頭にアンダースコアが付きます。プロパティ名がtempArrayであるため、インスタンス変数の名前は_tempArrayです。インスタンス変数tempArray自体が存在せず、コード行が無効です。

したがって、代わりに次のように書いたとします。

-(void) sampleFunction
{
  NSArray *myArray = [[NSArray alloc] init]; // (1)
  self.tempArray = myArray; // (2)
  self.tempArray = myArray; // (3)
  self.tempArray = [NSArray arrayWithObject:@"SomeString"]; // (4)
}
  • (1) では、NSArray の新しいインスタンスを作成しています。「alloc」は常に参照カウント 1 で新しいインスタンスを初期化します
  • (2) で記述しますself.tempArray = myArray(これは、プロパティ セッターと同等で[self setTempArray:myArray];あり、したがって呼び出します)。そのため、(1) で作成した同じ配列を指すようにプロパティを設定します。myArrayしたがって、この配列はプロパティによって保持され、プロパティによって保持されるため、retainCount が 1 増加しself.tempArrayます。
  • (3) では、以前とまったく同じオブジェクトにプロパティに影響を与えます。これにより、参照カウントはまったく変更されません。の値を別の値に置き換えたかのself.tempArrayように、プロパティのセッターが古い値を解放し (ref カウントを減らして)、新しい値を保持します (したがって、ref カウントを増やします)。あなたの場合、古い値と新しい値は同じオブジェクトであるため、配列の参照カウントをデクリメントしてから、再度インクリメントします。実際には、プロパティ セッターのデフォルトの実装は次のとおりであるため、オブジェクトの潜在的な解放を回避するために、ref カウントは (デクリメント + インクリメントを再度行う代わりに) まったく変更されません。

    -(void)setTempArray:(NSArray*)newValue
    {
      // check if old and new value are different. Only do sthg if they are different
      if (newValue != _tempArray)
      {
        [_tempArray release];  // release old value
        [newValue retain];     // retain new value
        _tempArray = newValue; // store new value in the backing variable associated with the property
      }
    }
    
  • (4) では、プロパティの値を再度置き換えますtempArrayが、今回はまったく新しいオブジェクトに置き換えます。そのため、プロパティは古い値を解放し、新しい値を保持します。したがって、(1) で作成した refcount が 2 の最初の配列 (myArrayおよび によって保持されるself.tempArray) は、その参照カウントを 1 に減らします (プロパティはそれを保持しなくなるため)。作成した新しいインスタンス[NSArray arrayWithObject:@"SomeString"]は、によって保持されます。プロパティなので、その参照カウントは +1 です。


(プロパティの使用を) インスタンス変数の直接使用に置き換えた場合self.tempArray = ...、インスタンス変数を使用しても、影響を受けるオブジェクトは保持されません (ただし、ARC を使用しているが使用していないように見える場合を除く)。 (2)、(3)、(4) では、オブジェクトの参照カウントはまったく変更されません。

于 2012-10-14T15:58:40.193 に答える
2

まず最初に、retainCount に頼ろうとさえしないでください。

その後、列挙したシナリオの中でどのシナリオが発生するのか疑問に思っています。まあ、どちらでもない。

なんで?最初に、インスタンス変数に直接割り当てているため、保持カウントは変更されません。まったく。ARC を使用している場合を除きますが、使用していないようです。

おそらく、オブジェクトのプロパティに何かを割り当てたい、つまり、書き込みたいと思ったでしょう。

self.tempArray = myArray;

プロパティ自体 (およびそのバッキング ivar ではない!) が として宣言されているためretain対応するアクセサ メソッドは、プロパティに割り当てられているオブジェクトの参照カウントを増やします。ただし、メモリリークを防ぐために、アクセサメソッドは通常、割り当て時に以前に割り当てられたオブジェクトを解放し、新しいオブジェクトを保持することによって実装されます。

- (void)setTempArray:(NSArray *)tmp
{
    [tmp retain];
    [tempArray release];
    tempArray = tmp;
}

したがって、基本的にmyArray、プロパティに再割り当てするself.tempArrayと、参照が失われて取得されるため、参照カウントはまったく変化しません。

別の新しい配列をプロパティに割り当てるとmyArray、refcount が再び失われ、0 にドロップされて割り当てが解除され、使用して作成された新しい配列+ [NSArray arrayWithObject:]が保持されます。alloc - init - autoreleaseを使用して作成され(メソッドの実装方法)、プロパティによって保持されているため、この後の正確な参照カウントは 1 になるはずです。ただし、 によって返される値は、- retainCount依然として (決して) 信頼できません。

于 2012-10-14T15:43:31.253 に答える
0

あなたの特定の例では、ではtempArrayなく に直接割り当ててself.tempArrayいるため、retainCountはずっと 1 のままです。しかし、私があなたが意図したと思うことをした場合に何が起こるか見てみましょう.

Objective-C では、合成された保持プロパティには、これと機能的に同等のセッターがあります。

-(void) setTempArray:(NSArray *value)
{
    if(tempArray != value) {
        [tempArray release];
        tempArray = [value retain];
    }
}

これにより、新しいオブジェクトが割り当てられると保持カウントが増加し、同じオブジェクトに設定されると基本的に何もせず、何か他のものが割り当てられると解放されます。したがって、例の保持カウントは次のようになります。

-(void) sampleFunction
{
    NSArray *myArray = [[NSArray alloc] init]; // Retain count of 1
    self.tempArray = myArray; // 2
    self.tempArray = myArray; // still 2
    self.tempArray = [NSArray arrayWithObject:@"SomeString"]; 
    // myArray.retainCount is 1,
    // tempArray.retainCount is 2 but with 1 autorelease
    // myArray leaks
}
于 2012-10-14T15:48:16.033 に答える