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. Aside from the fact that nullptr is a reserved keyword, is there any designated reasoning for this decision?
在c++ 11标准中,我不理解为什么不允许使用nullptr地址,而允许使用自己的std::nullptr_t实例的地址。除了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. Is nullptr dynamically assigned an address just-in-time for comparisons and such? Or (probably more likely) perhaps is the compiler forcing a temporary copy of the underlying object?
当我通过直接传递nullptr调用这个函数时,每次都会得到不同的地址。nullptr是否会动态地分配一个地址以便进行比较?或者(可能更有可能)是编译器强制一个底层对象的临时拷贝?
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).
当然,这些都不是重要的信息,我只是发现为什么要实施这个特定的限制(以及为什么我看到我的行为)很有趣。
4 个解决方案
#1
78
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
. It doesn't matter that there's no alternative value for a nullptr_t
to have.
这就好比你不能取5的地址,即使你可以取一个整数的地址在给它值5之后。对于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 = …;
. The address you're seeing is that of the temporary.
当您将一个值传递给const & parameter或将一个值绑定到const引用时,就会生成一个临时对象,例如static_cast< T const & >(…)或声明一个名为引用T const & foo =…;你看到的地址是临时地址。
#2
27
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的地址,但可以获取另一个作为lvalue的nullptr_t对象的地址。
Alternatively, § 2.14.7 says this about nullptr
:
另外,§2.14.7说这关于nullptr:
The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t.
指针文字是关键字nullptr。它是std: nullptr_t类型的prvalue。
So what is a prvalue? § 3.10/1 answers that:
那么什么是prvalue呢?§3.10/1的答案:
A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue. — end example ]
prvalue(“纯”rvalue)不是xvalue。[示例:调用返回类型不是引用的函数的结果是prvalue。文字的值,如12、7.3e5或true也是一个prvalue。——最后的例子)
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
. It's part of those examples!
希望,在这个例子中尝试取这些东西的地址会更有意义为什么不能取nullptr的地址。这是这些例子的一部分!
#3
10
nullptr
is a (literal) constant, and these don't have a memory address, like any other literal constant in your code. It's similar to 0
, but of the special std::nullptr_t
type instead of void*
to avoid problems with overloading (pointers vs. integers).
nullptr是一个(文字的)常量,并且它们没有一个内存地址,就像代码中的任何其他文字常量一样。它类似于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. However, constant variables do have addresses, to point out the difference.
对于任何其他类型的任何其他文字常量(在c++中属于prvalue类别)都是如此,因为文字常量并不存储在程序中(仅作为出现它们的表达式的一部分),这就是为什么谈论地址没有任何意义。然而,常量变量确实有地址,以指出差异。
#4
4
Both true and false are keywords and as literals they have a type ( 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.
真和假都是关键字,作为文字,它们都有一个类型(bool)。nullptr是类型std::nullptr_t的指针,它是一个prvalue(你不能使用它的地址),而且nullptr是prvalue,所以你不能取它的地址,文字常量不存储在你的程序中。
It doesn't make sense to have address.
有地址是没有意义的。
#1
78
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
. It doesn't matter that there's no alternative value for a nullptr_t
to have.
这就好比你不能取5的地址,即使你可以取一个整数的地址在给它值5之后。对于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 = …;
. The address you're seeing is that of the temporary.
当您将一个值传递给const & parameter或将一个值绑定到const引用时,就会生成一个临时对象,例如static_cast< T const & >(…)或声明一个名为引用T const & foo =…;你看到的地址是临时地址。
#2
27
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的地址,但可以获取另一个作为lvalue的nullptr_t对象的地址。
Alternatively, § 2.14.7 says this about nullptr
:
另外,§2.14.7说这关于nullptr:
The pointer literal is the keyword nullptr. It is a prvalue of type std::nullptr_t.
指针文字是关键字nullptr。它是std: nullptr_t类型的prvalue。
So what is a prvalue? § 3.10/1 answers that:
那么什么是prvalue呢?§3.10/1的答案:
A prvalue (“pure” rvalue) is an rvalue that is not an xvalue. [ Example: The result of calling a function whose return type is not a reference is a prvalue. The value of a literal such as 12, 7.3e5, or true is also a prvalue. — end example ]
prvalue(“纯”rvalue)不是xvalue。[示例:调用返回类型不是引用的函数的结果是prvalue。文字的值,如12、7.3e5或true也是一个prvalue。——最后的例子)
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
. It's part of those examples!
希望,在这个例子中尝试取这些东西的地址会更有意义为什么不能取nullptr的地址。这是这些例子的一部分!
#3
10
nullptr
is a (literal) constant, and these don't have a memory address, like any other literal constant in your code. It's similar to 0
, but of the special std::nullptr_t
type instead of void*
to avoid problems with overloading (pointers vs. integers).
nullptr是一个(文字的)常量,并且它们没有一个内存地址,就像代码中的任何其他文字常量一样。它类似于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. However, constant variables do have addresses, to point out the difference.
对于任何其他类型的任何其他文字常量(在c++中属于prvalue类别)都是如此,因为文字常量并不存储在程序中(仅作为出现它们的表达式的一部分),这就是为什么谈论地址没有任何意义。然而,常量变量确实有地址,以指出差异。
#4
4
Both true and false are keywords and as literals they have a type ( 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.
真和假都是关键字,作为文字,它们都有一个类型(bool)。nullptr是类型std::nullptr_t的指针,它是一个prvalue(你不能使用它的地址),而且nullptr是prvalue,所以你不能取它的地址,文字常量不存储在你的程序中。
It doesn't make sense to have address.
有地址是没有意义的。