我想检查 dynamic_cast 的结果,在 C++11 (或者对于支持 nullptr 的编译器使用 C++0x),我应该将其与 nullptr 还是 0 进行比较?
这是否重要,如果重要的话,为什么?
结果是否取决于编译器?
我想检查 dynamic_cast 的结果,在 C++11 (或者对于支持 nullptr 的编译器使用 C++0x),我应该将其与 nullptr 还是 0 进行比较?
这是否重要,如果重要的话,为什么?
结果是否取决于编译器?
常量nullptr
(类型为nullptr_t
)和常量0
都可以隐式转换为任何指针类型的空值。因此,对它们任意一个进行比较都是可以的,并且在技术上是正确的。顺便说一下,这意味着dynamic_cast
不返回任何一个,它会返回特定指针类型的空值。
最好养成使用nullptr
而非0
的习惯。据我所知,只有在正确的重载决议(例如,其中一个重载接受int
,另一个接受char*
)时才真正需要使用0
。为了保持一致,避免使用0
是最好的。
我所说的“指针类型的空值”是什么意思?
考虑变量char * ptr
。它的类型是(毫不意外地)char *
。但nullptr
的类型是特殊类型nullptr_t
。因此,当我们写ptr = nullptr
时,一些技术细节必须发生:
nullptr
必须隐式转换为char *
。ptr
的新值。char *
的空值是将nullptr
转换为char *
的结果。在概念上,它仍然是nullptr
,但是类型不同(char *
)。这个空值与int *
或string *
或任何其他指针类型的空值是不同的。我们往往认为这些空值只是nullptr
(或0
),但实际上每一个都是一个来自不同类型的不同值。(顺便说一下,使用==
进行比较时也会发生相同的转换。)
尽管这听起来像是琐碎的细节,但在重载决议中非常重要:
void foo(char * ptr) { ... }
void foo(int i) { ... }
void foo(nullptr_t ptr) { ... }
int main()
{
foo(0); // Calls void foo(int), since 0 is an int
foo(nullptr); // Calls void foo(nullptr_t), since nullptr is a nullptr_t
foo(new char('c')); // Calls void foo(char *), since new char('c') is a char*
}
或在分配不相关的空值时:
char * c_ptr = nullptr; // Okay
int * i_ptr1 = nullptr; // Okay
int * i_ptr2 = c_ptr; // COMPILER ERROR HERE
在布尔上下文中评估结果:
Base * p = get();
if (Derived * q = dynamic_cast<Derived *>(p))
{
q->derived_method();
}
else
{
// *p isn't of type Derived
}
nullptr
一直存在),因为它适用于比仅与nullptr
相比较的类型更多的类型。它适用于任何具有空概念的类型,表示为空转换为bool
,例如optional<T>
。我还认为对于像std::function
这样可与nullptr
进行比较但实际上不是指针类型的类型,它看起来更漂亮! - Ken Wayne VanderLinde
if (nullptr == dynamic_cast<foo*>(p))
时,nullptr
首先被转换为foo*
的空值,然后进行比较? - Patrick0
和nullptr
转换为指针类型时,必须与指针类型的空值相等。如果在bool
上下文中评估指针,则指针类型的空值必须评估为 false,非空值则为 true。然而,大多数环境将空指针存储为一堆零位。 :) - Yakk - Adam Nevraumont