1

私が次のようなインターフェースを持っていると仮定します:

@interface it:NSObject
{
  NSString* string;
}
@end

@implement it
-(id)init
{
  if(self = [super init]){
    self.string = [[NSString alloc]init];
  }
}

-(void)dealloc
{
   [self.string release];
   [super release];
}
@end

このクラスを別のファイルで使用し、これを呼び出す場合:

it ait = [[it allow] init];
NSString* anotherString = [[NSString alloc] init];
ait.string = anotherString;
[anotherString release];

これにより、そのinitメソッドに割り当てられた文字列がメモリリークを引き起こしますか?文字列が参照されておらず、自動解放されていないため。initメソッドで文字列を割り当てないと、anotherStringを割り当てる直前にait.stringを呼び出すとどうなりますか?

4

4 に答える 4

1

私はあなたが必要だと思います

@property (nonatomic, retain) NSString *string;

あなたのインターフェースで

@synthesize string;

self.stringが機能するように実装します。

次に、あなたがするとき

self.string = [[NSString alloc] init];

initメソッドでは[[NSString alloc] init]、保持カウントが1の文字列を返すため、文字列の保持カウントは実際には2にself.string =なります。プロパティが「保持」として宣言されているため、を使用するとオブジェクトが再び保持されます。これによりメモリリークが発生しますが、次の方法で修正できます。

-(id)init
{
  if(self = [super init]){
    self.string = @"initString";
  }
}

または類似。

self.string =次に、実際の質問に対して、上記のように行うと、「retain」とマークされたプロパティが新しいオブジェクトを保持する前に現在のオブジェクトを解放するため、で再割り当てしたときにinitに割り当てられた文字列がリークしません。

initメソッドで文字列を割り当てない場合は、が返されるだけself.stringなので問題ありません。これは、プログラムで処理できます。self.stringnil

于 2011-03-12T08:38:02.387 に答える
0

これにより、そのinitメソッドに割り当てられた文字列がメモリリークを引き起こしますか?文字列が参照されておらず、自動解放されていないため。

はい、正確に。あなたはそれを持っているようです。

initメソッドで文字列を割り当てないと、anotherStringを割り当てる直前にait.stringを呼び出すとどうなりますか?

次の場合、unknownObjectが何を参照するのかわからないということですか?:-

It *ait = [[It allow] init];
NSString *unknownObject = ait.string;

これはナンセンスです。アクセサメソッドを追加するのを忘れましたか?

Objective-cは、Javaなどのインスタンス変数にアクセスするために「ドット構文」を使用しません。クラス'it'のインスタンスがある場合は、アクセサ'getter'メソッドを呼び出すことによってそのインスタンスの外部からのみ'string'変数にアクセスできます。これはオプションではありません。self.stringはメソッド呼び出し[selfstring]のショートカットであり、このメソッドは表示されたコードには存在しません。

アクセサメソッドが他の場所で定義されていると仮定すると、stringと呼ばれるインスタンス変数(これは世界で最悪の変数名です)nilに等しくなります。Objective-cでは、動作が他の多くの言語が同様のnullを処理するのとは異なるため、nilオブジェクトを非常に注意深く処理する必要があります。

Objective-cではこれで問題ありません。

NSString *nilString = nil;
[nilString writeToFile:@"/this_file_cannot_exist.data"];

他の多くの言語はここでクラッシュするか、例外をスローします。操作は失敗する可能性がありますが、アプリは引き続き実行されるため、これは危険な場合があります。他の言語ではこれがたくさん見られるので、それは素晴らしいことでもあります。

someObject = controller.currentValue()
if( someObject!=null )
  someObject.writeToFile("myFile.data")

Objective-cでは、「if(..)」行はまったく必要ありません。

initメソッドとdeallocメソッド内でアクセサメソッドを呼び出さないように注意する必要があります。これにより、サブクラスが破損する可能性があります。それ以外の

- (void)dealloc {
   [self.string release]; // This is [[self string] release]
   ...

あなたはただ使うべきです

- (void)dealloc {
   [string release];
   ...

危険であるだけでなく、[自己文字列]の呼び出しも不要です。同じことがあなたのinitメソッドにも当てはまります

if(self=[super init]){
  self.string = [[NSString alloc]init]; // shortcut for [self setString:[[NSString alloc] init]]
  ...

使用するだけ

if(self=[super init]){
  string = [[NSString alloc] init];
  ...
于 2011-03-12T09:36:32.157 に答える
0
@interface it:NSObject
{
  NSString* string;
}

//you should declare a property in order to call it with 'self' prefix
@property (nonatomic, retain) NSString* string;

@end


@implementation it

//you should synthesize your property
@synthesize string;

-(id)init
{
  if(self = [super init]){
    //you don't to initialize NSString right here (memory leak will have place)
    //self.string = [[NSString alloc]init];

    //you can store a default value like this (can be omitted):
    self.string = @"Default value";
  }
  return self;
}

-(void)dealloc
{
   [self.string release];
   [super release];
}
@end

そして、このクラスのメモリ管理に関するすべてがうまくいくでしょう。

于 2011-03-12T08:33:35.207 に答える
0

self.stringを使用するための@propertyがありません。

これを.hファイルに追加します

@property(readwrite、copy)NSString * string;

Retainの代わりにCopyを使用すると、anotherStringを解放しても、文字列のメモリリークが防止されます。

于 2011-03-12T09:45:36.527 に答える