2
Line 1: First.h
Line 2: @property (nonatomic, retain) NSString *name;

Line  3: First.m
Line  4: @synthesize name;
Line  5: -(void)viewDidLoad()
Line  6: {
Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc]initWithString:@"Hello"]; 
Line 10:                          OR
Line 11:  }
Line 12:-(void)dealloc()
Line 13: {
Line 14: [name release];
Line 14: } 

質問 1:
行番号 7 に従えばすべて問題なく、行番号 9 を使用するとメモリ リークが発生します。私が知っているように、自己は現在のオブジェクトを指しており、使用したself.object場合と単にobject違いがない場合です。

質問2:そして、私が使用した場合

@synthesize name = _name;

では、どちらが name の値を設定するためのもので、どちらが値を取得するためのものでしょうか? との差:

name = [NSString stringWithString:@"Hello"];
            OR
self.name = [NSString stringWithString:@"Hello"];
            OR
_name = [NSString stringWithString:@"Hello"];

質問 3:
プロパティを作成する場合、メモリ リークを示すために割り当てたメモリを割り当てる必要はありますか?

4

3 に答える 3

2

最初の質問に答えるには:alloc作成したオブジェクトを保持しているメソッドで文字列を初期化するため、リークが発生しますが、後でオブジェクトを解放しstringWithStringないため、自動解放されたオブジェクトを取得して文字列を作成しているときにリークが発生します自動解放プールによって自動的に解放されます。9行目の例では、オブジェクトを初期化してプロパティのセッターに渡していることに注意してください.ivarを使用した場合は状況が異なります...

2 番目の質問に答えるには、プロパティ名を合成し、それを名前付きの内部変数 (ivar) に関連付けているため_name、クラス内で ivar を使用してプロパティの値にアクセスできます_name

メモリ管理に関する Appleのドキュメントを読むことを強くお勧めします。

于 2012-10-13T07:18:58.193 に答える
2

質問 1: 行番号 7 に従えばすべて問題なく、行番号 9 を使用するとメモリ リークが発生します。私が知っているように、selfは現在のオブジェクトを指しており、self.objectまたは単にオブジェクトを使用した場合、それ以上の違いはありません。

Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc]initWithString:@"Hello"]; 

7 行目では、自動解放されたオブジェクトを返す便利なコンストラクターを使用し、オブジェクトをivarに直接割り当てています。name現在、自動解放されたオブジェクトを保持プロパティに割り当てることは問題ありませんが、自動解放されたオブジェクトを明示的に保持せずに ivar に直接割り当てることは正しくありません。

name = [[NSString stringWithString:@"Hello"] retain];

9 行目では、保持されたオブジェクトを提供する alloc/init を使用しています。このようなオブジェクトを ivar に直接割り当てるのは正しいですが、retain プロパティに割り当てる前に自動解放する必要があります。

self.name = [[[NSString alloc]initWithString:@"Hello"] autorelease]; 

これについては、オブジェクト保持カウントの観点から推論できます。

  1. 便利なコンストラクターは保持カウントを 1 に設定しますが、これは後でreleaseフレームワークによって行われる呼び出しによって自動的に減少します。

  2. alloc/init は、明示的に呼び出さない限り減少しない保持カウント 1 を提供しますrelease

  3. オブジェクト保持カウントが 0 になると、割り当てが解除されます。

保持数に関する推論は、このメモリ管理の問題全体を見て、フレームワークの奥深くで何が起こっているかを理解するための方法にすぎません。ただし、これがオブジェクトのライフサイクルを分析する適切な方法であるとは限りません。

では、どちらが name の値を設定するためのもので、どちらが値を取得するためのものでしょうか? name = [NSString stringWithString:@"Hello"];OR self.name = [NSString stringWithString:@"Hello"];ORの違い_name = [NSString stringWithString:@"Hello"];

name = [NSString stringWithString:@"Hello"];

_name = [NSString stringWithString:@"Hello"];

与えられた2つのケースではまったく同じです。これにより、プロパティの setter(/getter) メソッドがバイパスされ、ivar に直接割り当てられます。この場合、自動解放されたオブジェクトを ivar に直接割り当てているため、アプリは遅かれ早かれクラッシュします。これは正しいでしょう:

_name = [[NSString stringWithString:@"Hello"] retain];

また

_name = [[NSString alloc] initWithString:@"Hello"];

ivar を として宣言するプログラムでは、 を使用して参照_nameできないことに注意してください。質問1のようにivarを明示的に指定せずにプロパティのみを宣言した場合は、ivarを直接参照するためにname使用できます(この場合、コンパイラによって自動的に生成されたivarになります)。namename

一方で:

self.name = [NSString stringWithString:@"Hello"]; 

プロパティ アクセサー メソッド (実際にはセッター) を使用します。あなたのプロパティは として宣言されてretainいるので、便利なコンストラクタによって返された autoreleased 変数をそれに割り当てても問題ありませんstringWithString:

質問 3: プロパティを作成する場合、メモリ リークを示すようにメモリを割り当てる必要がありますか?

これは私にはよくわかりません。

メモリ管理の基本について読むのに適したドキュメントは、Apple の Advanced Memory Management Programming Guide のMemory Management PolicyおよびPractical Memory Managementです。

于 2012-10-13T07:22:47.410 に答える
0

最初にいくつかの背景、MRCの概念のみの要約:

メモリ管理はすべて所有権に関するものです。オブジェクトを所有している限り、そのオブジェクトは存在します。所有権を放棄した後、オブジェクトは破棄されます。オブジェクトへの参照は事実上無効であり、所有権を放棄した後は使用しないでください。

所有権は排他的ではありませんが、共有モデルに従います。常に複数の所有者が存在する可能性があり、オブジェクトに所有者がいない場合にのみ、オブジェクトを破棄できるようになります。

オブジェクトを一時的に使用する必要がある場合、たとえば単一のコードブロック内でのみ使用する必要がある場合は、必ずしも所有権を取得する必要はありません。これは、所有権がどのように放棄されたかの結果の一部です。所有権をすぐに放棄するのではなく、後で所有権を放棄するように要求できます。

後でアプリケーションの実行の特定のポイントで発生し、そのようなポイントが手動で追加されない限り、実行ループの各サイクルの実行後にそのようなポイントが1つあります。

所有権retain、自分が所有するオブジェクトを返す呼び出しまたはメソッドの呼び出しによって表明されます。最も一般的なのallocは、copy他のオブジェクトです。所有権は、への呼び出しを使用して放棄releaseされます。後でへの呼び出しを使用して放棄されautoreleaseます。

質問1:

Line  7:     name = [NSString stringWithString:@"Hello"];
Line  8:                          OR
Line  9:     self.name = [[NSString alloc] initWithString:@"Hello"]; 

7行目の右側(RHS)は、所有していないオブジェクトへの参照を返します。左側(LHS)は、この参照をインスタンス変数 nameに割り当てます。これで、所有していないものへの参照が保存されました。これは、オブジェクトの所有者が所有権を放棄し、オブジェクトが破棄され、に無効な参照があるため、これは悪いnameことです。レッスン:*所有していないオブジェクトへの参照をインスタンス変数に保存しないでください。

一方、9行目のRHSは、所有しているオブジェクトへの参照を返します。ただし、LHSはプロパティ呼び出し self.nameを使用して参照を格納します。これはretainプロパティであるため、所有権も取得します。これで2回所有するようになりました。これは悪いことですが、別の方法の場合です。所有権を2回放棄しない限り、おそらくそうはなりませんが、オブジェクトには常に所有者がいて、一般にリークと呼ばれる永久に存続します。

コードを入れ替える場合:

Line  7a:     name = [[NSString alloc] initWithString:@"Hello"];
Line  8a:                          OR
Line  9b:     self.name = [NSString stringWithString: @"Hello"]; 

その後、それはあなたが期待することをします。7a行目のRHSは、所有しているオブジェクト参照を返し、LHSはそれをプロパティによって管理されるインスタンス変数 に格納します。name name

9a行目のRHSは、所有していないオブジェクト参照を返しますが、LHSはプロパティ呼び出しを使用し、プロパティには属性の所有権があり、インスタンス変数retainに格納されている参照は所有されているオブジェクトに対するものです。 name

いずれの場合も、プロパティが属性を持っているために現在のインスタンス( self)が破棄されると、インスタンス変数によるオブジェクト参照の所有権は放棄されます。nameretainname

質問2

使用の影響は何ですか:

@synthesize name = _name;

これは、プロパティ が。ではなくインスタンス変数nameを使用することを意味します。コードスニペットでは、宣言しないか、両方が;によって自動的に宣言されます。したがって、に応じて、またはインスタンス変数のいずれかのみが存在します。したがって、質問2の答えは、インスタンス変数へのすべての参照が。に置き換えられた質問1の答えです。 _namenamename_name@synthesizename_name@synthesizename_name

質問3

この質問を理解していて、理解できるかどうかわからない場合は、質問1の回答でカバーされています。

HTH

于 2012-10-13T18:02:38.690 に答える