【发布时间】:2009-12-03 18:40:59
【问题描述】:
目前我将其理解为一种“空对象”。但它到底是什么?
【问题讨论】:
-
克尔凯郭尔和尼采是你的向导。
标签: objective-c cocoa cocoa-touch null
目前我将其理解为一种“空对象”。但它到底是什么?
【问题讨论】:
标签: objective-c cocoa cocoa-touch null
首先,当你调用这个时:
id someObject = [NSArray array];
someObject 不是直接的数组对象,而只是指向它的指针。这意味着,如果someObject 等于0x1234,则内存中该地址处有一个对象。
这就是原因
id someOtherObject = someObject;
不复制对象。现在两个指针都指向同一个对象。
那么,nil 是如何定义的?我们看一下源码:
objc.h
#define nil __DARWIN_NULL /* id of Nil instance */
_types.h
#ifdef __cplusplus
…
#else /* ! __cplusplus */
#define __DARWIN_NULL ((void *)0)
#endif /* __cplusplus */
看起来nil 是指向地址 0x0 的指针。
让我们看看Objective-C Programming Reference 怎么说:
向 nil 发送消息
在 Objective-C 中,发送一个 给 nil 的消息——它根本没有效果 在运行时。有几种模式 在 Cocoa 中利用这一点 事实。从 a 返回的值 发给 nil 的消息也可能是有效的:……
返回值是nil、0 或struct,所有变量都初始化为0。它是哪一个取决于预期的返回类型。在objective-c 运行时中有一个显式检查发送到nil 的消息,这意味着它非常快。
Nil, nil, NULL
这是3种类型。以下是所有定义:
#define Nil __DARWIN_NULL /* id of Nil class */
#define nil __DARWIN_NULL /* id of Nil instance */
#define NULL __DARWIN_NULL
#define __DARWIN_NULL ((void *)0)
可以看出,它们都完全相同。 Nil 和 nil 由 Objective-C 定义,NULL 来自 C。
那有什么区别呢?这只是关于风格。它使代码更具可读性。
Nil 用作不存在的类:Class someClass = Nil。nil 用作不存在的实例:id someInstance = nil。NULL 是指向不存在的内存部分的指针:char *theString = NULL。nil 不是一个空对象,而是一个不存在的对象。 -getSomeObject 方法如果不存在则不会返回空对象,而是返回 nil,告诉用户没有对象。
也许这是有道理的:(两者都可以编译和运行。)
if (anObject == nil) { // One cannot compare nothing to nothing,
// that wouldn't make sense.
if (anObject) { // Correct, one checks for the existence of anObject
【讨论】:
nil 进行比较是完全有效的。您甚至可能会争辩说,它比单纯的指针作为真值表达式更明确地是 nil-check(尽管我自己使用真值表达式形式)。
nil,从逻辑上讲不可能将“无对象”与“无对象”进行比较,但说起来很容易“如果此对象存在,请执行此操作”。
if (nil == nil) 没有意义,但if (anObject == nil) 可以:“如果变量anObject 中没有对象……”
anObject 的变量”,但就像anObject 一样。这种简化在大多数情况下都有效。只要您将其视为pointer to an object,将其与nil 进行比较就非常有意义。
这不是一个空的对象,而是根本没有任何对象。其余的答案涵盖了其他语义,所以我将保留它:)
【讨论】:
nil 只能与指针一起使用,nil 表示指向 nothing 的指针(其值为 0)
NSString *myString = nil; // myString points to nothing
int x = nil; // invalid, "x" is not a pointer, but it will compile
【讨论】:
这是“无”。但是,如果您尝试在 NULL 上调用方法,您可以向其发送消息而不会被杀死的“无”。
您可以查看this 问题以了解有关NULL 与nil 的更多信息
【讨论】:
NULL 发送消息,它的行为与nil 完全相同,因为两者都是0 的值给计算机。我什至认为nil 的typedefd 为NULL。
Nil、nil 和 NULL 都定义为 __DARWIN_NULL,因此完全可以互换。但有一些逻辑上的差异。
NULL 发送消息的问题。出于这个非常具体的原因,我一直非常积极地说“在NULL 上调用方法”。但是,即使它们可以互换,我相信每个语义都需要在代码中进行翻译。仅仅因为你可以做蹩脚的编码并不意味着你应该。
这是一个null pointer - 指向“无”的指针。
【讨论】:
正式定义,正如Joshual所定义的——指向空的指针或指向任何对象的指针。
从实际的实现角度来看,特别是在处理数据结构和算法时,nill 通常表示数据结构中的哨兵或表示“无”的对象,例如,在技术上,在红黑树中,所有叶节点都是“nill”,但它们仍然具有叶节点相同或相似的属性和操作(颜色、指向父节点的指针等)——在这些情况下,它实际上是一个“无对象”。 .. 如果这有任何意义。
所以,形式上,它是一个空指针,在实践中,它通常被视为空的表示,但它永远不会......为空。
【讨论】:
思考nil 的一种有用方式是想象它是“什么都不做”的空对象。
我所说的“什么都不做”是指您发送的任何消息都不会产生副作用。
它是“空的”,因为当你向它询问任何属性的值时,它总是返回nil。所以它不包含任何值 --> 它是空的。
(实际上,它比这更复杂一点,当您要求返回一个不是 obj-c 对象的类型的属性的值时。您将返回一个指针大小的0。所以对于任何标量值不大于sizeof(void*) 你会得到0。但如果你在32位系统上要求struct或double,你会得到未定义的结果。我写过关于这个here。)
【讨论】:
也许我只是错过了显而易见的问题,但这似乎是一个语义问题。比如,你可以用很多不同的词来描述它,但你的描述已经足够好了。
【讨论】:
澄清一下,在 Objective-C 中,nil 和 null 不是一回事。它们在 Objective-C 中所代表的东西也不像在数学或其他编程语言中所代表的那样。
Nil实际上是一个特殊的内存地址0x0(至少编译器把它当成一个地址)。Nil被用作一个已命名但未分配的对象的地址。这允许测试命名对象的存在/分配,并提供一种安全的方式将消息发送到可能不存在的对象。在数学和某些语言中,您可以将标量变量与 nil 进行比较,但在 Objective-c 中,您不应该这样做。您应该只比较对象的地址。
相比之下,NULL 可以表示标准 C 定义为NULL==0 的整数值,也可以表示具有特定内存地址的NSNull 类的实际分配对象。然而,NSNull 是一个单例对象,即每个应用程序只存在一个对象。它通常用作集合中其他对象的占位符。您不能将其用于与任何其他对象进行比较。您只能检查特定指针是否指向单例 NSNull 对象。但请注意,作为已分配对象[NSNull null]!=NULL,
nil 和 NULL 之间的混淆是因为分配 NULL 地址将其分配给 0x0 的 nil 地址。这样的代码可以工作,但有时会导致微妙的问题。最好养成不要混淆两者的习惯。
因此,在 Objective-C 中,nil、NUll 和 NSNull 是三个不同但重叠的概念,很容易混淆。 Nil 应该用于地址,NULL 应该用于标量值,NSNull 应该用作分配对象的占位符。
【讨论】:
nil 与NULL 交换。两者都只是值0x0。
NULL 通常定义为 (void*),而不是整数。 C++ 在这方面有所不同,原因不值得一提,但在这两种语言中,NULL 通常仅用于指针类型。 NULL 是 not 标量,不应该这样使用。