为什么C ++中没有“NULL引用”?

时间:2012-07-10 07:49:38

标签: c++ pointers reference null specifications

我正在阅读C ++常见问题 - “8.6 - When should I use references, and when should I use pointers?”,特别是这句话:

  

尽可能使用引用,并在必要时使用指针。

     

...

     

上面的例外是函数的参数或返回值需要“sentinel”引用 - 一个不引用对象的引用。这通常最好通过返回/获取指针,并给出NULL指针这一特殊意义(引用必须始终为别名对象,而不是取消引用的NULL指针)。

从我所看到的,对“哨兵”引用的需求确实经常是使用指针而不是引用的原因。我想知道的是:为什么C ++没有特殊的“NULL值”用于引用?它似乎会使指针几乎不必要,这将解决许多问题。

那么为什么它不是语言规范的一部分呢?

修改

我不确定我的问题是否清楚 - 我想我不是故意要求NULL引用。我经常在C ++中读到“引用是对象”。而且,在大多数OOP语言中,对象可以是NULL - Pascal,C#,Java,JavaScript,PHP等,所有这些都可以someObject = nullsomeObject := nil。事实上,Pascal也支持指针,但仍然允许对象为nil,因为它有它的用途。那么为什么C ++在某种程度上是特殊的并且没有NULL对象呢?这只是一个忽视或实际的决定吗?

5 个答案:

答案 0 :(得分:13)

因为引用带有语义,它指向永远不会改变的有效内存地址;即解除引用它是安全/定义的,因此不需要NULL检查。参考文献不能通过设计重新分配。

当var可以为NULL并且客户端代码必须处理该情况时,您使用指针。如果可以保证有效/初始化的内存地址,则使用引用。

使用指针的一个示例是作为类的成员,用于存储某些实例的“引用”,这些实例可能在类构造时可能未知或无法初始化。但是,成员参考必须在施工时初始化(通过初始化列表),并且不能推迟其分配。

如果允许空引用,那么除了语法之外,它与指针没有区别(需要进行相同的NULL检查。)

<强>更新

  

“而且,在大多数OOP语言中,对象可以是NULL - Pascal,C#,Java,JavaScript,PHP等等。[...]那么为什么C ++有些特殊并且没有NULL对象?是吗?只是一个忽视或实际的决定?“

我觉得你对此有点困惑。 Java和C#等可能给人一种“NULL对象”的印象,但这些对象引用或多或少类似于C ++指针,具有更简单的语法,GC检测和异常抛出。在这些语言中,如果您使用“Null对象”,您将获得某种异常,例如 NullReferenceException (C#)。地狱,在Java中称为 NullPointerException

您必须先检查null,然后才能安全使用它们。有点像C ++指针(除了在大多数托管语言中,默认情况下指针初始化为NULL,而在C ++中,它通常取决于您设置初始指针值(否则未定义/已存在的任何内存)。)< / p>

C ++视图是关于选择的,因此是详细的:

  • 使用普通指针做你喜欢的事,在必要时检查NULL。
  • 使用具有编译器强制有效语义/约束的引用。
  • 滚动自己的智能指针进行记账,并按照您希望的方式行事。
  • 如果需要,使用void指针(小心!)引用无类型的内存块。

答案 1 :(得分:6)

请看一下指针和引用之间的区别 - 虽然标准使得引用如何实现,但它们目前总是作为指针实现。

这意味着它们之间的主要区别是a)语义b)指针可以重新安装c)指针可以为null。

所以简短的回答是,这是故意的。当你作为程序员看到一个引用你应该知道a)该引用被填充b)它不会改变(和c)你可以使用与对象相同的语义。)

标准是否允许空引用,在使用引用之前,您总是必须检查null,这是不需要的。

编辑:

关于你的编辑,我想这里的混乱可能源于这样一个事实,即大多数更简单的OO语言隐藏了正在发生的事情。以Java为例,虽然看起来你有NULL对象,并且可以分配它们,但你真的不能 - 真正发生的是Java只有指针,并且可以为这些指针分配空值。由于不可能直接在Java中实现对象,因此它们取消了指针语义并将指针视为对象。 C ++功能更强大 - 容易出错(Java爱好者会说不需要堆栈用户类实例,并且决定不在Java中使用它们来降低复杂性,并使Java更易于使用)。由此可见,由于Java没有对象,因此它没有引用。但是,实际上没有帮助的是,Java调用C ++人称之为指针传递值的传递方式。

答案 2 :(得分:1)

按定义引用应与另一个变量或对象相关联。因此,空或空参考类型违反了它的存在目的。

从技术上讲,这意味着你从空引用开始,然后将它指定给某个变量,或者可能后者重新分配给另一个变量。这根本不是为什么创建的。

指针的其他一些用途,引用可能根本无法复制。例如,使用指针指向具有少量存储器的大块复杂数据(字节序列),并且通过仅花费8个字节左右来指示所需的频率。你不能在不浪费同等记忆的情况下用引用来做到这一点。

引用始终与类型相关联,而指针则不是这样。

答案 3 :(得分:1)

在大多数其他语言使用该术语的意义上,C ++引用不是引用;它更像是别名。使用C ++引用不涉及“取消引用”它与取消引用指针的方式相同;它有效地 分配给它的对象。

实际上并不存在空对象实例这样的东西,因此您无法创建对此类事物的C ++引用。在其他语言中,空引用相当于C ++空指针;它实际上并没有包含任何东西。

现在,关于你的其他想法:1。拥有不可空的引用是我脑海中的一个的东西;它意味着您可以获得通过引用传递的所有好处,而无需在整个地方检查空值。 2.可空引用不替换指针...如果您需要在低级别执行内存或IO工作,您将需要原始访问内存和内存映射设备。你可以看一下C#(或C ++ / CLR),它正是由于这个原因而管理了引用和非托管指针。

答案 4 :(得分:0)

引用必须引用某些内容,因此,null引用不可用 C没有引用,我们只能使用这种语言的指针,因此,这是与C语言的兼容性