2012-08-17 4 views
6

-initメソッドがselfのメッセージのみを呼び出すと仮定すると、メッセージnilが有効でない場合self != nilかどうかをチェックするのはなぜですか?メッセージnilが効果を持たない場合、なぜself!= nilで-initをチェックするのですか?

のは、次のように我々は初期化子を持っているとしましょう:

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     [self doThis]; 
     [self setFoo:@"Bar"]; 
    } 

    return self; 
} 

代わりselfをチェックする、私たちは書くことができます:

- (id)init 
{ 
    self = [super init]; 
    [self doThis]; 
    [self setFoo:@"Bar"]; 

    return self; 
} 

を今すぐnilを返し[super init]何らかの理由で、何の違いもないならば方法の結果として私が知る限り。それでは、なぜこのチェックをいつも行っていますか?

答えて

7

メッセージをnilに送信できますが、インスタンス変数nilにはアクセスできません。 EXC_BAD_ACCESS例外が発生します。 [super init]リターンは、この例ではnilをどうなり

@implementation MyObject { 
    int instanceVariable; 
} 

- (id)init { 
    self = [super init]; 
    instanceVariable = 7; 
    return self; 
} 

は、インスタンス変数を持つクラスを考えてみましょうか? nullポインタのinstanceVariableにアクセスしようとすると例外が発生します。

インスタンス変数にアクセスしていない場合でも、self == nilをチェックしないと、他のものが間違ってしまう可能性があります。 malloc - 割り付けられたメモリやファイルハンドルを簡単に漏らすことができます。または、nilを期待していないメソッドに自分自身を渡すこともできます。

他の回答では、nilをチェックしないとオブジェクトがリークする可能性があります。例:

selfがnilであっても、これはARCでリークしません。手動参照カウント(MRC)の下では、から+1保持カウントのバランスをとることはないため、この例ではselfがゼロであるかどうかにかかわらずリークします。

MRCの下でそれを行うための適切な方法はこれです:

- (id)init { 
    self = [super init]; 
    [self setSomeProperty:[[[NSObject alloc] init] autorelease]]; 
} 

またはこの:

- (id)init { 
    self = [super init]; 
    NSObject *object = [[NSObject alloc] init]; 
    [self setSomeProperty:object]; 
    [object release]; 
    return self; 
} 

それらのどちらがselfがnilであるかどうか、リークが発生します。

あなたはsetterメソッドをバイパスする場合は、次のように、あなただけのselfがnilであれば、クラッシュます:ターン戻りはnilで行った[スーパーのinit]場合

- (id)init { 
    self = [super init]; 
    _someProperty = [[NSObject alloc] init]; 
    return self; 
} 
+0

これはむしろシグナルです.Cには例外がありません。 –

+1

+1、素晴らしい答え。 –

+0

これはC++例外ではなく、CPU例外です。 '/ usr/include/mach/exception_types.h'を見てください。 –

0

、その後、あなたは、おそらく多くを割り当ててしまうでしょうあなたが自己を返すとき、あなたはゼロを返すでしょう。これらのオブジェクトは解放されません。

+0

最後に、@robは正しいです - これは実際の理由ではありません。 –

+0

@ user1606088しかし、落胆しないでください。これはかなり微妙な問題です。 –

関連する問題