【问题标题】:Why can't you take the address of nullptr?为什么不能取nullptr的地址?
【发布时间】:2012-12-20 19:32:04
【问题描述】:

在 C++11 标准中,我不明白为什么不允许使用 nullptr 的地址,而 允许使用自己的 std::nullptr_t 实例的地址.除了nullptr 是保留关键字这一事实之外,是否有任何指定的理由来做出此决定?

仅仅因为它让我感到有趣,我试图用以下函数绕过这个限制:

decltype(nullptr)* func(const decltype(nullptr) &nref) noexcept
{
    return const_cast<decltype(nullptr)*>(reinterpret_cast<const decltype(nullptr)*>(&nref));
}

我不得不在参数上使用reinterpret_cast,因为没有它我会得到歇斯底里的错误:

error: invalid conversion from 'std::nullptr_t*' to 'std::nullptr_t*' [-fpermissive]

当我通过直接传递 nullptr 调用此函数时,我每次都会得到一个不同的地址。 nullptr 是否为比较等动态分配了一个地址?或者(可能更有可能)编译器是否强制创建底层对象的临时副本?

当然,这些都不是重要信息,我只是觉得有趣的是为什么要实施这个特定的限制(以及后来为什么我会看到我的行为)。

【问题讨论】:

  • nullptr 是prvalue。你不能拿那些地址。不过,为错误消息 +1。

标签: c++ c++11 std nullptr


【解决方案1】:

这与无法获取5 的地址相同,即使您在将值5 后可以获取int 的地址。 nullptr_t 没有其他值并不重要。

值没有地址;对象可以。

当您将这样的值传递给const &amp; 参数,或以其他方式将值绑定到常量引用(例如通过static_cast&lt; T const &amp; &gt;( … ) 或声明命名引用T const &amp; foo = …;)时,会生成一个临时对象。您看到的地址是临时地址。

【讨论】:

  • 谢谢!我实际上是在挖掘更多,我偶然发现了this answer to a related question。然后我突然意识到 nullptr 是作为空指针文字的,是吗?您无法获取文字的地址是有道理的。 :)
  • 是的,nullptr 是代表文字的关键字。就像truefalse 一样(你也不能使用&amp;true)。
  • 是的! :DI 认为当我阅读“空指针 constant”时,我只是将其阅读为“logical constant”而不是“literal constant” .
  • 恭喜你获得新的最佳答案,顺便说一句 :)
【解决方案2】:

如果您追求标准答案,第 18.2/9 节会直言不讳地说明您的观察结果:

虽然不能取nullptr的地址,但是可以取另一个nullptr_t对象的地址,它是左值 被带走。

或者,第 2.14.7 节对nullptr 进行了说明:

指针字面量是关键字 nullptr。它是 std::nullptr_t 类型的纯右值。

那么什么是prvalue? § 3.10/1 回答:

prvalue(“纯”右值)是一个不是 xvalue 的右值。 [ 示例:调用函数的结果 返回类型不是引用的就是prvalue。诸如 12、7.3e5 或 true 等文字的值是 也是prvalue。 —结束示例]

希望,在示例中尝试获取任何这些东西的地址对于为什么不能获取nullptr 的地址更有意义。这是这些示例的一部分!

【讨论】:

  • 啊,直到现在我才知道prvalue是什么,+1。
  • @SethCarnegie,我喜欢他们的定义。有时当我通过标准来完全定义某些东西时,它让我想起了递归。
  • @SethCarnegie,我忘记了这一点,但如果它不仅仅是prvalues,请查看this question 以了解其他喜欢它的人。
  • @chris 哦,太棒了,我没看过,收藏了。顺便说一句,我发现最有趣的答案(对于这个问题)比你的投票多约 30 个。我不知道为什么会这样。
  • @SethCarnegie,在投了很多票之后,我回答得有点晚了,但是在这个答案中真正让你“哦”的东西是最后的引用,如果您会注意到,最佳答案已经完成,只是更简单和即时。我的意思是这是一个证明,人们可以按照标准查看为什么这是无效的。
【解决方案3】:

nullptr 是一个(文字)常量,它们没有内存地址,就像代码中的任何其他文字常量一样。它类似于0,但具有特殊的std::nullptr_t 类型而不是void*,以避免重载问题(指针与整数)。

但是如果你定义自己的变量为nullptr,它有一个内存地址,所以你可以取它的地址。

这同样适用于任何其他类型的任何其他文字常量(在 C++ 中属于 prvalue 类别),因为文字常量不存储在您的程序中(仅作为它们出现的表达式的一部分),这就是为什么谈论地址没有任何意义。但是,常量变量确实有地址,以指出区别。

【讨论】:

    【解决方案4】:

    true 和 false 都是关键字,并且作为文字它们有一个类型( bool )。 nullptr 是 std::nullptr_t 类型的指针文字,它是一个纯右值(你不能使用 & 获取它的地址),nullptr 也是纯右值,所以你不能获取它的地址,文字常量不存储在你的程序中。

    有地址没有意义。

    【讨论】:

      猜你喜欢
      • 2012-10-17
      • 2012-07-02
      • 2011-07-08
      • 2022-01-02
      • 2011-12-22
      • 2020-01-08
      • 1970-01-01
      • 1970-01-01
      • 2012-02-25
      相关资源
      最近更新 更多