简体   繁体   English

为什么不能取nullptr的地址?

[英]Why can't you take the address of nullptr?

In the C++11 standard, I don't understand the reason why taking the address of nullptr is disallowed whereas one is allowed to take the address of their own std::nullptr_t instances. 在C ++ 11标准,为什么服用nullptr是不允许的,而一个地址允许拿自己的std :: nullptr_t实例的地址,我不明白其中的道理。 Aside from the fact that nullptr is a reserved keyword, is there any designated reasoning for this decision? 除了nullptr是保留关键字这一事实之外,是否有任何指定的推理作出此决定?

Simply because it amuses me, I attempted to circumnavigate this restriction with the following function: 仅仅因为它让我很开心,我试图用以下函数环绕这个限制:

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

I had to use reinterpret_cast on the parameter because without it I was getting the hysterical error: 我不得不在参数上使用reinterpret_cast,因为没有它我得到了歇斯底里的错误:

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

When I call this function by passing nullptr directly I get a different address each time. 当我通过直接传递nullptr来调用此函数时,每次都会得到一个不同的地址。 Is nullptr dynamically assigned an address just-in-time for comparisons and such? 是否为nullptr动态分配地址及时进行比较等? Or (probably more likely) perhaps is the compiler forcing a temporary copy of the underlying object? 或者(可能更有可能)编译器可能强制执行底层对象的临时副本?

Of course none of this is vital information, I just find it interesting why this particular restriction was implemented (and subsequently why I am seeing the behavior I am). 当然,这些都不是至关重要的信息,我只是觉得有趣的是为什么要实施这一特定的限制(以及随后为什么我会看到我的行为)。

It's the same as not being able to take the address of 5 even though you can take the address of an int after giving it the value 5 . 即使你可以在赋予值5之后获取int的地址,但是无法取5的地址是一样的。 It doesn't matter that there's no alternative value for a nullptr_t to have. nullptr_t没有替代值也nullptr_t

Values don't have addresses; 值没有地址; objects do. 对象呢。

A temporary object is generated when you pass such a value to a const & parameter, or otherwise bind a value to a const reference, such as by static_cast< T const & >( … ) or declaring a named reference T const & foo = …; const &值传递给const &参数时生成临时对象,或者将值绑定到const引用,例如通过static_cast< T const & >( … )或声明命名引用T const & foo = …; . The address you're seeing is that of the temporary. 你看到的地址是临时的。

If you're after a standard answer, § 18.2/9 puts your observations pretty bluntly: 如果您正在接受标准答案,§18.2/ 9会非常坦率地表达您的观察结果:

Although nullptr's address cannot be taken, the address of another nullptr_t object that is an lvalue can be taken. 虽然无法获取nullptr的地址,但可以采用另一个作为左值的nullptr_t对象的地址。

Alternatively, § 2.14.7 says this about nullptr : 或者,§2.14.7说明了nullptr

The pointer literal is the keyword nullptr. 指针文字是关键字nullptr。 It is a prvalue of type std::nullptr_t. 它是std :: nullptr_t类型的prvalue。

So what is a prvalue? 什么是prvalue? § 3.10/1 answers that: §3.10/ 1回答:

A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. prvalue(“纯”rvalue)是一个不是xvalue的rvalue。 [ Example: The result of calling a function whose return type is not a reference is a prvalue. [示例:调用返回类型不是引用的函数的结果是prvalue。 The value of a literal such as 12, 7.3e5, or true is also a prvalue. 诸如12,7.3e5或true之类的文字的值也是prvalue。 — end example ] - 结束例子]

Hopefully, trying to take the address of any of those things in the example will make more sense as to why you can't take the address of nullptr . 希望尝试在示例中获取任何这些内容的地址将更有意义,为什么你不能采用nullptr的地址。 It's part of those examples! 这是这些例子的一部分!

nullptr is a (literal) constant, and these don't have a memory address, like any other literal constant in your code. nullptr是一个(文字)常量,它们没有内存地址,就像代码中的任何其他文字常量一样。 It's similar to 0 , but of the special std::nullptr_t type instead of void* to avoid problems with overloading (pointers vs. integers). 它类似于0 ,但是使用特殊的std::nullptr_t类型而不是void*来避免重载问题(指针与整数)。

But if you define your own variable with the value nullptr , it has a memory address, so you can take its address. 但是如果使用值nullptr定义自己的变量,它就有一个内存地址,因此您可以获取其地址。

The same holds for any other literal constant (which in C++ fall under the category prvalue ) of any other type, since literal constants aren't stored in your program (only as parts of expressions where they occur), that's why it doesn't make any sense to talk about addresses. 对于任何其他类型的任何其他文字常量(在C ++中属于类别prvalue )也是如此,因为文字常量不存储在程序中(仅作为它们出现的表达式的一部分),这就是为什么它不存在谈谈地址是否有意义。 However, constant variables do have addresses, to point out the difference. 但是,常量变量确实有地址,以指出差异。

Both true and false are keywords and as literals they have a type ( bool ). true和false都是关键字,而文字则是一个类型(bool)。 nullptr is a pointer literal of type std::nullptr_t, and it's a prvalue (you cannot take the address of it using &), also nullptr is prvalue so you can't take its address,literal constants are not stored in your program. nullptr是std :: nullptr_t类型的指针文字,它是一个prvalue(你不能使用&获取它的地址),nullptr也是prvalue所以你不能取其地址,文字常量不会存储在你的程序中。

It doesn't make sense to have address. 有地址没有意义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM