【问题标题】:What describes nil best? What's that really?什么描述 nil 最好?那真的是什么?
【发布时间】:2009-12-03 18:40:59
【问题描述】:

目前我将其理解为一种“空对象”。但它到底是什么?

【问题讨论】:

  • 克尔凯郭尔和尼采是你的向导。

标签: objective-c cocoa cocoa-touch null


【解决方案1】:

Objective-C 对象

首先,当你调用这个时:

id someObject = [NSArray array];

someObject 不是直接的数组对象,而只是指向它的指针。这意味着,如果someObject 等于0x1234,则内存中该地址处有一个对象。

这就是原因

id someOtherObject = someObject;

不复制对象。现在两个指针都指向同一个对象。

指向 0x0 的指针

那么,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)

可以看出,它们都完全相同。 Nilnil 由 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 进行比较就非常有意义。
【解决方案2】:

这不是一个空的对象,而是根本没有任何对象。其余的答案涵盖了其他语义,所以我将保留它:)

【讨论】:

  • 这是迄今为止最好的答案。
【解决方案3】:

nil 只能与指针一起使用,nil 表示指向 nothing 的指针(其值为 0)

NSString *myString = nil; // myString points to nothing
int x = nil; // invalid, "x" is not a pointer, but it will compile

【讨论】:

    【解决方案4】:

    这是“无”。但是,如果您尝试在 NULL 上调用方法,您可以向其发送消息而不会被杀死的“无”。

    您可以查看this 问题以了解有关NULLnil 的更多信息

    【讨论】:

    • 您可以根据需要向NULL 发送消息,它的行为与nil 完全相同,因为两者都是0 的值给计算机。我什至认为nil 的typedefd 为NULL
    • NilnilNULL 都定义为 __DARWIN_NULL,因此完全可以互换。但有一些逻辑上的差异。
    • 如果您仔细阅读我的声明,您会注意到我从未说您会遇到崩溃或任何向NULL 发送消息的问题。出于这个非常具体的原因,我一直非常积极地说“在NULL 上调用方法”。但是,即使它们可以互换,我相信每个语义都需要在代码中进行翻译。仅仅因为你可以做蹩脚的编码并不意味着你应该
    【解决方案5】:

    这是一个null pointer - 指向“无”的指针。

    【讨论】:

      【解决方案6】:

      正式定义,正如Joshual所定义的——指向空的指针或指向任何对象的指针。

      从实际的实现角度来看,特别是在处理数据结构和算法时,nill 通常表示数据结构中的哨兵或表示“无”的对象,例如,在技术上,在红黑树中,所有叶节点都是“nill”,但它们仍然具有叶节点相同或相似的属性和操作(颜色、指向父节点的指针等)——在这些情况下,它实际上是一个“无对象”。 .. 如果这有任何意义。

      所以,形式上,它是一个空指针,在实践中,它通常被视为空的表示,但它永远不会......为空。

      【讨论】:

        【解决方案7】:

        思考nil 的一种有用方式是想象它是“什么都不做”的空对象。

        我所说的“什么都不做”是指您发送的任何消息都不会产生副作用。

        它是“空的”,因为当你向它询问任何属性的值时,它总是返回nil。所以它不包含任何值 --> 它是空的。
        (实际上,它比这更复杂一点,当您要求返回一个不是 obj-c 对象的类型的属性的值时。您将返回一个指针大小的0。所以对于任何标量值不大于sizeof(void*) 你会得到0。但如果你在32位系统上要求structdouble,你会得到未定义的结果。我写过关于这个here。)

        【讨论】:

          【解决方案8】:

          也许我只是错过了显而易见的问题,但这似乎是一个语义问题。比如,你可以用很多不同的词来描述它,但你的描述已经足够好了。

          http://en.wikipedia.org/wiki/Null_(computer_programming)

          【讨论】:

            【解决方案9】:

            澄清一下,在 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 应该用作分配对象的占位符。

            【讨论】:

            • 我很确定在 no 种情况下无法将nilNULL 交换。两者都只是值0x0
            • 在 C 中,NULL 通常定义为 (void*),而不是整数。 C++ 在这方面有所不同,原因不值得一提,但在这两种语言中,NULL 通常仅用于指针类型。 NULL 是 not 标量,不应该这样使用。
            • 这是文体问题。用 NULL 代替 nil 是不好的做法,因为 NULL 通常用于表示未定义。例如,在 SQL 中 NULL 有特殊的含义。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-06-08
            • 1970-01-01
            • 1970-01-01
            • 2017-04-13
            • 1970-01-01
            • 1970-01-01
            • 2011-03-15
            相关资源
            最近更新 更多