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

为了更清楚我在说什么,这里有一个例子。

有这个类:

@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

4 回答 4

67

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

文档

向零发送消息

在 Objective-C 中,向 nil 发送消息是有效的——它在运行时根本不起作用。Cocoa 中有几种模式利用了这一事实。从消息返回到 nil 的值也可能是有效的:

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

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

    如果aPerson'sspousenil,则mother发送到nil并且方法返回nil

  • 如果该方法返回任何指针类型、任何大小小于或等于sizeof(void*)、a float、a double、along double或 a 的整数标量long long,则发送到的消息将nil返回0

  • 如果该方法返回 a struct,如 Mac OS X ABI 函数调用指南中定义的那样,将在寄存器中返回,那么发送到的消息将 nil返回0.0数据结构中的每个字段。其他struct 数据类型不会用零填充。

  • 如果该方法返回上述值类型以外的任何值,则发送到 nil 的消息的返回值是未定义的。

于 2010-04-23T07:33:11.493 回答
13

格雷格帕克网站

如果运行 LLVM 编译器 3.0 (Xcode 4.2) 或更高版本

返回类型为 nil 的消息 | 返回
高达 64 位的整数 | 0
浮点数高达 long double | 0.0
指针 | 零
结构 | {0}
任何_复杂类型 | {0, 0}
于 2012-02-29T22:45:06.917 回答
6

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

从 Objective-C 的第一个版本开始,给 nil 的消息一直是返回 nil 的安全空操作。有很多代码取决于这种行为。

于 2010-04-23T08:47:59.270 回答
0

没啥事儿。当您向 nil 发送消息时,这意味着没有接收者并且消息飞走了。objc_msgSend方法是从Runtime库中使用的。Message dispatch使用机制,这就是为什么Objective-C不同,并且基于此原理有很多优点。它不会像JavaSwift那样抛出任何错误

于 2021-02-18T14:27:50.573 回答