在未初始化的对象上调用方法(空指针)

时间:2010-04-23 07:29:42

标签: iphone objective-c initialization null-pointer

  1. 如果你在一个nil的对象(指针)上调用一个方法(也许是因为有人忘了初始化它),Objective-C中的正常行为是什么?它不应该产生某种错误(分段错误,空指针异常......)?
  2. 如果这是正常行为,有没有办法改变这种行为(通过配置编译器),以便程序在运行时引发某种错误/异常?
  3. 为了使我所说的更清楚,这是一个例子。

    有这个课程:

    @interface Person : NSObject {
    
        NSString *name;
    
    }
    
    @property (nonatomic, retain) NSString *name;
    
    - (void)sayHi;
    
    @end
    

    有了这个实现:

    @implementation Person
    
    @synthesize name;
    
    - (void)dealloc {
        [name release];
        [super dealloc];
    }
    
    - (void)sayHi {
        NSLog(@"Hello");
        NSLog(@"My name is %@.", name);
    }
    
    @end
    

    在程序的某个地方,我这样做:

    Person *person = nil;
    //person = [[Person alloc] init]; // let's say I comment this line
    person.name = @"Mike";            // shouldn't I get an error here?
    [person sayHi];                   // and here
    [person release];                 // and here
    

4 个答案:

答案 0 :(得分:61)

发送到nil对象的消息在Objective-C中是完全可以接受的,它被视为无操作。没有办法将它标记为错误,因为它不是错误,事实上它可能是该语言的一个非常有用的功能。

来自docs

  

将消息发送给nil

     

在Objective-C中,发送一个   消息为零 - 它根本没有效果   在运行时。有几种模式   在Cocoa,利用这一点   事实。从a返回的值   消息为零也可能有效:

     
      
  • 如果方法返回一个对象,则返回发送到nil的消息   0nil),例如:

         

    Person *motherInLaw = [[aPerson spouse] mother];

         

    如果aPerson的{​​{1}}是spouse,   然后nil被发送到mother和。{1}}   方法返回nil

  •   
  • 如果方法返回任何指针类型,则任何大小均小的整数标量   等于nil,a   sizeof(void*)floatdouble,   或long double,然后发送消息   到long long返回nil

  •   
  • 如果方法返回{Mac} X ABI定义的0   函数调用指南将被退回   寄存器,然后发送消息   struct为每个字段返回nil   数据结构。其他0.0   数据类型不会被填充   零。

  •   
  • 如果方法返回上述值以外的任何值   键入消息的返回值   发送到nil是未定义的。

  •   

答案 1 :(得分:13)

来自Greg Parkersite

如果运行LLVM Compiler 3.0(Xcode 4.2)或更高版本

Messages to nil with return type | return
Integers up to 64 bits           | 0
Floating-point up to long double | 0.0
Pointers                         | nil
Structs                          | {0}
Any _Complex type                | {0, 0}

答案 2 :(得分:6)

您应该清楚的一点是,在Objective-C中,您没有对象上调用方法,您向对象发送消息。运行时将找到该方法并调用它。

从Objective-C的第一个版本开始,向nil发送消息一直是一个安全的无操作,返回nil。有很多代码依赖于这种行为。

答案 3 :(得分:0)

什么都没发生。当您向 nil 发送消息时,表示没有接收者 然后消息飞走了。 SELECT category, Item, Currency, Discount FROM yourTable t1 WHERE EXISTS (SELECT 1 FROM yourTable t2 WHERE t2.category = t1.category AND t2.Item = t1.Item AND t2.Discount > t1.Discount); 方法来自 objc_msgSend 库。使用了Runtime 机制,这就是为什么Message dispatch 不同的原因,并且基于此原理有很多优点。它不会像 Objective-CJava do

那样抛出任何错误