【问题标题】:Why not call nullptr NULL?为什么不调用 nullptr NULL?
【发布时间】:2015-11-24 23:29:04
【问题描述】:

在 C++11 中,nullptr 关键字被添加为更安全的空指针常量,因为之前将 NULL 定义为 0 存在一些问题。

为什么标准委员会选择不调用新的空指针常量NULL,或者声明NULL应该是#defined到nullptr

【问题讨论】:

标签: c++ c++11 language-design


【解决方案1】:

Stephan T. Lavavej(C++ 标准委员会成员)曾在 talk (55:35) 中解释说:

虽然允许实现#define NULL nullptr,但它会破坏很多用途,例如

int i = NULL;

显然有很多这样的。所以他们不能强迫改变。

【讨论】:

  • 我曾希望他们至少会弃用 this,以便将来可以将 NULL 定义为 nullptr...(或者可以将 nullptr 称为 NULL 和 nullptr_t可能有一个不推荐的转换为 int)
  • 对于与int 案例类似的示例,我偶尔会遇到有人用str[end_pos] = NULL;“空终止”他们的字符串的代码。
  • int i = NULL; 一直是邪恶的。你为什么要这样做?
  • @TNA 嗯,C 在这方面有点邪恶。这就像使用str[end_pos] = NULLstr[end_pos] = 0,或者使用13 而不是\r,例如——都是常用的。类型在 C 中并不是什么大问题... 另一个例子是被广泛滥用的 long,尤其是与指针通常转换为 intlong 的方式结合使用时。 “发明”int i = NULL 的人可能认为这是一种非常明显的说法,即“现在int i 已初始化为默认值”。很遗憾,但 C 中有很多类似的做法。
  • @Luaan C 允许将NULL 定义为((void*) 0) 并且已经使int i = NULL; 在技术上非法。
【解决方案2】:

nullptr指针类型 ,而 NULL 倾向于是整数,有时在重载的函数中,你需要清楚你使用的是指针而不是整数- 这就是nullptr 派上用场的时候。

所以要真正回答你的问题,NULLnullptr 有两个不同的目的,重新定义一个到另一个可能会破坏已经存在的代码库中的很多东西。

除此之外,请从Bjarne Stroustrup's website查看此内容:

我应该使用 NULL 还是 0?

在C++中,NULL的定义是0,所以只有审美 区别。我更喜欢避免使用宏,所以我使用 0。另一个问题是 NULL是人们有时错误地认为它是不同的 从 0 和/或不是整数。在准标准代码中,NULL 是/是 有时被定义为不合适的东西,因此必须/必须 避免。这几天不太常见了。如果你必须命名为空 指针,称它为nullptr;这就是它在 C++11 中的名称。然后, "nullptr" 将是一个关键字。

【讨论】:

  • 但这就是问题所在 - 为什么不将 NULL 更改为 nullptr 呢?
  • @immibis 因为你不能将 int 变量(只是一个例子)初始化为指针类型 NULL(即 nullptr),这将是一个很大的问题。
  • 技术上,nullptr 不是指针类型,而是nullptr_t 类型。
  • @Hurkyl ,当然我只是想让这个概念更清楚,也许你应该编辑答案以包含它。
【解决方案3】:

NULL 不是类型安全的。由于历史原因,它被定义为没有强制转换的 0,并且编译器将强制转换数字的警告静音到这个特殊零上的指针。

瞬间,你可以这样做:

void* p = 0;

如果没有隐式转换,则不是这样:

void* p = 1234;

副作用是它可以被滥用为数字值,正如其他答案所提到的那样。

nullptr 通过强制它是一个指针来改进它,你不能将它分配给一个整数。 由于行为发生了变化,因此为向后兼容创建了一个新名称。

还要注意,nullptr 由编译器处理,它的实际值不会暴露给用户(就像在NULL 的情况下为零)。在不影响程序员的代码逻辑的情况下,拥有依赖于架构的值要容易得多,比如0xdeadbeef

【讨论】:

  • 现在我很想吃些死牛肉。
  • @dubstylee 0xfeedface 0xdeadbeef? 0xfeedface 0xcafef00d! (我们曾经有一个 4 位十六进制显示的系统,小组中的每个人都知道几乎每个只包含字符 a、b、c、d、e、f、i 和 o 的 4 字母单词,并使用他们互相交谈。)
【解决方案4】:

如果没有实际参与标准委员会的讨论,很难确定,但我认为因为它会破坏一些使用NULL 的代码,而nullptr 的兼容性不足。打破旧代码从来都不是一个好主意。

【讨论】:

    【解决方案5】:

    为什么标准委员会选择不调用新的空指针常量NULL

    大概是因为新的空指针是一个关键字,而关键字不能是#defined,所以称它为NULL 会包含任何可能格式错误的C 标头。

    或者声明NULL应该是#definednullptr

    标准委员会确实允许NULL 成为#definednullptr,但它并不要求这样做。

    C++11 18.2 类型 [support.types]/2: 宏 NULL 是本国际标准中实现定义的 C++ 空指针常量。

    C++11 4.10 指针转换[conv.ptr]/1空指针常量是整数类型的整数常量表达式 (5.19) 纯右值,其计算结果为零或std::nullptr_t 类型的纯右值。

    这里不考虑向后兼容性,任何假定NULL 是整数0 的形式的使用都不符合标准。实现可能会选择不这样做以纵容这种邪恶行为。

    【讨论】:

      【解决方案6】:

      我将演示一个将 nullptr 定义为不同类型的决定有助于防止错误的案例。

      考虑这些函数:

      void foo(int);
      void foo(char *);
      
      int main()
      {
          foo(NULL); // oops
      }
      

      在 C++98 中,上面的代码调用了 foo(int) 函数,因为 NULL 被 0 替换了,这很可能不是你想要的。

      但如果你调用 foo(nullptr) 它会调用正确的 -- foo(char*)

      【讨论】:

      • 如果 foo(NULL) 将 NULL 更改为 nullptr 也会如此。
      • @immibis 是的,但他们不想破坏现有代码,这是我同意的。
      【解决方案7】:

      nullptr 是为了类型安全和清晰而引入的(可能是为了停止使用 NULL 的非指针类型的初始化)。

      NULL(int type) 未更改为nullptr(pointer type) 以避免混淆并确保向后兼容性。

      因此,标准委员会的思路可能与从旧符号到新符号的平稳过渡有关,而不会引起歧义或破坏任何现有代码。

      【讨论】:

      • 使 NULL 成为指针类型导致混淆?如果有什么我认为它会避免混淆。
      • @immibis 它说:“NULL(int 类型)未更改为 nullptr(指针类型)”以避免混淆,并且在问题的上下文中。混淆涉及types,这就是为什么我明确地把它们放在后面澄清。当然,创建指针NULL 不会引起混淆,但已接受的答案 向您展示了为什么NULL 的类型未更改为nullptr 的示例。
      猜你喜欢
      • 1970-01-01
      • 2013-12-28
      • 2012-10-17
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 2012-07-02
      • 2015-11-24
      • 1970-01-01
      相关资源
      最近更新 更多