43

在 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为比较等即时动态分配地址?或者(可能更有可能)编译器是否强制底层对象的临时副本?

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

4

4 回答 4

82

这与无法获取地址相同,5即使您可以int在给它 value 之后获取地址5。a 没有其他价值并不重要nullptr_t

值没有地址;对象做。

当您将此类值传递给const &参数时,或者将值绑定到 const 引用(例如通过static_cast< T const & >( … )或声明命名引用)时,会生成一个临时对象T const & foo = …;。您看到的地址是临时地址。

于 2013-01-07T04:03:29.113 回答
28

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

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

或者,第 2.14.7 节这样说nullptr

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

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

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

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

于 2013-01-07T04:18:33.713 回答
10

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

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

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

于 2013-01-07T04:09:45.443 回答
4

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

没有地址是没有意义的。

于 2013-01-07T09:43:20.257 回答